calc_lib/
lib.rs

1//! [![git]](https://git.philomathiclife.com/calc_rational/log.html) [![crates-io]](https://crates.io/crates/calc_rational) [![docs-rs]](crate)
2//!
3//! [git]: https://git.philomathiclife.com/git_badge.svg
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6//!
7//! `calc_lib` is a library for performing basic rational number arithmetic using standard operator precedence
8//! and associativity. Internally, it is based on
9//! [`Ratio<T>`] and [`BigInt`].
10//!   
11//! ## Expressions  
12//!   
13//! The following are the list of expressions in descending order of precedence:  
14//!   1. number literals, `@`, `()`, `||`, `round()`, `rand()`  
15//!   2. `!`  
16//!   3. `^`  
17//!   4. `-` (unary negation operator)  
18//!   5. `*`, `/`, `mod`  
19//!   6. `+`, `-`  
20//!   
21//! All binary operators are left-associative sans `^` which is right-associative.  
22//!   
23//! Any expression is allowed to be enclosed in `()`. Note that parentheses are purely for grouping expressions;
24//! in particular, you cannot use them to represent multiplication (e.g., `4(2)` is grammatically incorrect and
25//! will result in an error message).  
26//!   
27//! Any expression is allowed to be enclosed in `||`. This unary operator represents absolute value.  
28//!   
29//! `!` is the factorial operator. Due to its high precedence, something like *-i!^j!* for *i, j ∈ ℕ* is
30//! the same thing as *-((i!)^(j!))*. If the expression preceding it does not evaluate to a non-negative integer,
31//! then an error will be displayed. Spaces  and tabs are *not* ignored; so `1 !` is grammatically incorrect and
32//! will result in an error message.  
33//!   
34//! `^` is the exponentiation operator. The expression left of the operator can evaluate to any rational number;
35//! however the expression right of the operator must evaluate to an integer or ±1/2 unless the expression on
36//! the left evaluates to `0` or `1`. In the event of the former, the expression right of the operator must evaluate
37//! to a non-negative rational number. In the event of the latter, the expression right of the operator can evaluate to
38//! any rational number. Note that `0^0` is defined to be 1. When the operand right of `^` evaluates to ±1/2, then
39//! the left operand must be the square of a rational number.  
40//!   
41//! The unary operator `-` represents negation.  
42//!   
43//! The operators `*` and `/` represent multiplication and division respectively. Expressions right of `/`
44//! must evaluate to any non-zero rational number; otherwise an error will be displayed.  
45//!   
46//! The binary operator `mod` represents modulo such that *n mod m = r = n - m\*q* for *n,q ∈ ℤ, m ∈ ℤ\\{0}, and r ∈ ℕ*
47//! where *r* is the minimum non-negative solution.  
48//!   
49//! The binary operators `+` and `-` represent addition and subtraction respectively.  
50//!   
51//! With the aforementioned exception of `!`, all spaces and tabs before and after operators are ignored.  
52//!   
53//! ## Round expression  
54//!   
55//! `round(expression, digit)` rounds `expression` to `digit`-number of fractional digits. An error will
56//! be displayed if called incorrectly.  
57//!   
58//! ## Rand expression  
59//!   
60//! `rand(expression, expression)` generates a random 64-bit integer inclusively between the passed expressions.
61//! An error will be displayed if called incorrectly. `rand()` generates a random 64-bit integer.  
62//!   
63//! ## Numbers  
64//!   
65//! A number literal is a non-empty sequence of digits or a non-empty sequence of digits immediately followed by `.`
66//! which is immediately followed by a non-empty sequence of digits (e.g., `134.901`). This means that number
67//! literals represent precisely all rational numbers that are equivalent to a ratio of a non-negative integer
68//! to a positive integer whose sole prime factors are 2 or 5. To represent all other rational numbers, the unary
69//! operator `-` and binary operator `/` must be used.  
70//!   
71//! ## Empty expression  
72//!   
73//! The empty expression (i.e., expression that at most only consists of spaces and tabs) will return
74//! the result from the previous non-(empty/store) expression in *decimal* form using the minimum number of digits.
75//! In the event an infinite number of digits is required, it will be rounded to 9 fractional digits using normal rounding
76//! rules first.  
77//!   
78//! ## Store expression  
79//!   
80//! To store the result of the previous non-(empty/store) expression, one simply passes `s`. In addition to storing the
81//! result which will subsequently be available via `@`, it displays the result. At most 8 results can be stored at once;
82//! at which point, results that are stored overwrite the oldest result.  
83//!   
84//! ## Recall expression  
85//!   
86//! `@` is used to recall previously stored results. It can be followed by any *digit* from `1` to `8`.
87//! If such a digit does not immediately follow it, then it will be interpreted as if there were a `1`.
88//! `@i` returns the *i*-th most-previous stored result where *i ∈ {1, 2, 3, 4, 5, 6, 7, 8}*.
89//! Note that spaces and tabs are *not* ignored so `@ 2` is grammatically incorrect and will result in an error message.
90//! As emphasized, it does not work on expressions; so both `@@` and `@(1)` are grammatically incorrect.  
91//!   
92//! ## Character encoding  
93//!   
94//! All inputs must only contain the ASCII encoding of the following Unicode scalar values: `0`-`9`, `.`, `+`, `-`,
95//! `*`, `/`, `^`, `!`, `mod`, `|`, `(`, `)`, `round`, `rand`, `,`, `@`, `s`, &lt;space&gt;, &lt;tab&gt;,
96//! &lt;line feed&gt;, &lt;carriage return&gt;, and `q`. Any other byte sequences are grammatically incorrect and will
97//! lead to an error message.  
98//!   
99//! ## Errors  
100//!   
101//! Errors due to a language violation (e.g., dividing by `0`) manifest into an error message. `panic!`s
102//! and [`io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html)s caused by writing to the global
103//! standard output stream lead to program abortion.  
104//!   
105//! ## Exiting  
106//!   
107//! `q` with any number of spaces and tabs before and after will cause the program to terminate.  
108//!   
109//! ### Formal language specification  
110//!   
111//! For a more precise specification of the “calc language”, one can read the
112//! [calc language specification](https://git.philomathiclife.com/calc_rational/lang.pdf).
113#![expect(
114    clippy::arithmetic_side_effects,
115    reason = "calculator can't realistically avoid this"
116)]
117#![no_std]
118#![cfg_attr(docsrs, feature(doc_cfg))]
119extern crate alloc;
120use LangErr::{
121    DivByZero, ExpDivByZero, ExpIsNotIntOrOneHalf, InvalidAbs, InvalidDec, InvalidPar, InvalidQuit,
122    InvalidRound, InvalidStore, MissingTerm, ModIsNotInt, ModZero, NotEnoughPrevResults,
123    NotNonNegIntFact, SqrtDoesNotExist, TrailingSyms,
124};
125use O::{Empty, Eval, Exit, Store};
126use alloc::{
127    string::{String, ToString as _},
128    vec,
129    vec::Vec,
130};
131use cache::Cache;
132#[cfg(not(feature = "rand"))]
133use core::marker::PhantomData;
134use core::{
135    convert,
136    fmt::{self, Display, Formatter},
137    ops::Index as _,
138};
139pub use num_bigint;
140use num_bigint::{BigInt, BigUint, Sign};
141use num_integer::Integer as _;
142pub use num_rational;
143use num_rational::Ratio;
144#[cfg(feature = "rand")]
145use num_traits::ToPrimitive as _;
146use num_traits::{Inv as _, Pow as _};
147#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
148#[cfg(feature = "rand")]
149pub use rand;
150#[cfg(feature = "rand")]
151use rand::{RngCore as _, rngs::ThreadRng};
152/// Fixed-sized cache that automatically overwrites the oldest data
153/// when a new item is added and the cache is full.
154///
155/// One can think of
156/// [`Cache`] as a very limited but more performant [`VecDeque`][alloc::collections::VecDeque] that only
157/// adds new data or reads old data.
158pub mod cache;
159/// Generalizes [`Iterator`] by using
160/// generic associated types.
161pub mod lending_iterator;
162/// Error due to a language violation.
163#[non_exhaustive]
164#[derive(Debug)]
165pub enum LangErr {
166    /// The input began with a `q` but had non-whitespace
167    /// that followed it.
168    InvalidQuit,
169    /// The input began with an `s` but had non-whitespace
170    /// that followed it.
171    InvalidStore,
172    /// A sub-expression in the input would have led
173    /// to a division by zero.
174    DivByZero(usize),
175    /// A sub-expression in the input would have led
176    /// to a rational number that was not 0 or 1 to be
177    /// raised to a non-integer power that is not (+/-) 1/2.
178    ExpIsNotIntOrOneHalf(usize),
179    /// A sub-expression in the input would have led
180    /// to 0 being raised to a negative power which itself
181    /// would have led to a division by zero.
182    ExpDivByZero(usize),
183    /// A sub-expression in the input would have led
184    /// to a number modulo 0.
185    ModZero(usize),
186    /// A sub-expression in the input would have led
187    /// to the mod of two expressions with at least one
188    /// not being an integer.
189    ModIsNotInt(usize),
190    /// A sub-expression in the input would have led
191    /// to a non-integer factorial or a negative integer factorial.
192    NotNonNegIntFact(usize),
193    /// The input contained a non-empty sequence of digits followed
194    /// by `.` which was not followed by a non-empty sequence of digits.
195    InvalidDec(usize),
196    /// A recall expression was used to recall the *i*-th most-recent stored result,
197    /// but there are fewer than *i* stored where
198    /// *i ∈ {1, 2, 3, 4, 5, 6, 7, 8}*.
199    NotEnoughPrevResults(usize),
200    /// The input did not contain a closing `|`.
201    InvalidAbs(usize),
202    /// The input did not contain a closing `)`.
203    InvalidPar(usize),
204    /// The input contained an invalid round expression.
205    InvalidRound(usize),
206    /// A sub-expression in the input had a missing terminal expression
207    /// where a terminal expression is a decimal literal expression,
208    /// recall expression, absolute value expression, parenthetical
209    /// expression, or round expression.
210    MissingTerm(usize),
211    /// The expression that was passed to the square root does not have a solution
212    /// in the field of rational numbers.
213    SqrtDoesNotExist(usize),
214    /// The input started with a valid expression but was immediately followed
215    /// by symbols that could not be chained with the preceding expression.
216    TrailingSyms(usize),
217    /// The input contained an invalid random expression.
218    #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
219    #[cfg(feature = "rand")]
220    InvalidRand(usize),
221    /// Error when the second argument is less than first in the rand function.
222    #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
223    #[cfg(feature = "rand")]
224    RandInvalidArgs(usize),
225    /// Error when there are no 64-bit integers in the interval passed to the random function.
226    #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
227    #[cfg(feature = "rand")]
228    RandNoInts(usize),
229}
230impl Display for LangErr {
231    #[inline]
232    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
233        match *self {
234            InvalidStore => f.write_str("Invalid store expression. A store expression must be of the extended regex form: ^[ \\t]*s[ \\t]*$."),
235            InvalidQuit => f.write_str("Invalid quit expression. A quit expression must be of the extended regex form: ^[ \\t]*q[ \\t]*$."),
236            DivByZero(u) => write!(f, "Division by zero ending at position {u}."),
237            ExpIsNotIntOrOneHalf(u) => write!(f, "Non-integer exponent that is not (+/-) 1/2 with a base that was not 0 or 1 ending at position {u}."),
238            ExpDivByZero(u) => write!(f, "Non-negative exponent with a base of 0 ending at position {u}."),
239            ModZero(u) => write!(f, "A number modulo 0 ending at position {u}."),
240            ModIsNotInt(u) => write!(f, "The modulo expression was applied to at least one non-integer ending at position {u}."),
241            NotNonNegIntFact(u) => write!(f, "Factorial of a rational number that was not a non-negative integer ending at position {u}."),
242            InvalidDec(u) => write!(f, "Invalid decimal literal expression ending at position {u}. A decimal literal expression must be of the extended regex form: [0-9]+(\\.[0-9]+)?."),
243            NotEnoughPrevResults(len) => write!(f, "There are only {len} previous results."),
244            InvalidAbs(u) => write!(f, "Invalid absolute value expression ending at position {u}. An absolute value expression is an addition expression enclosed in '||'."),
245            InvalidPar(u) => write!(f, "Invalid parenthetical expression ending at position {u}. A parenthetical expression is an addition expression enclosed in '()'."),
246            InvalidRound(u) => write!(f, "Invalid round expression ending at position {u}. A round expression is of the form 'round(<mod expression>, digit)'"),
247            SqrtDoesNotExist(u) => write!(f, "The square root of the passed expression does not have a solution in the field of rational numbers ending at position {u}."),
248            #[cfg(not(feature = "rand"))]
249            MissingTerm(u) => write!(f, "Missing terminal expression at position {u}. A terminal expression is a decimal literal expression, recall expression, absolute value expression, parenthetical expression, or round expression."),
250            #[cfg(feature = "rand")]
251            MissingTerm(u) => write!(f, "Missing terminal expression at position {u}. A terminal expression is a decimal literal expression, recall expression, absolute value expression, parenthetical expression, round expression, or rand expression."),
252            TrailingSyms(u) => write!(f, "Trailing symbols starting at position {u}."),
253            #[cfg(feature = "rand")]
254            Self::InvalidRand(u) => write!(f, "Invalid rand expression ending at position {u}. A rand expression is of the form 'rand()' or 'rand(<mod expression>, <mod expression>)'."),
255            #[cfg(feature = "rand")]
256            Self::RandInvalidArgs(u) => write!(f, "The second expression passed to the random function evaluated to rational number less than the first ending at position {u}."),
257            #[cfg(feature = "rand")]
258            Self::RandNoInts(u) => write!(f, "There are no 64-bit integers within the interval passed to the random function ending at position {u}."),
259        }
260    }
261}
262/// A successful evaluation of an input.
263#[derive(Debug)]
264pub enum O<'a> {
265    /// The input only contained whitespace.
266    /// This returns the previous `Eval`.
267    /// It is `None` iff there have been no
268    /// previous `Eval` results.
269    Empty(&'a Option<Ratio<BigInt>>),
270    /// The quit expression was issued to terminate the program.
271    Exit,
272    /// Result of a "normal" expression.
273    Eval(&'a Ratio<BigInt>),
274    /// The store expression stores and returns the previous `Eval`.
275    /// It is `None` iff there have been no previous `Eval` results.
276    Store(&'a Option<Ratio<BigInt>>),
277}
278impl Display for O<'_> {
279    #[expect(
280        unsafe_code,
281        reason = "manually construct guaranteed UTF-8; thus avoid the needless check"
282    )]
283    #[expect(clippy::indexing_slicing, reason = "comment justifies correctness")]
284    #[inline]
285    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
286        match *self {
287            Empty(o) => {
288                o.as_ref().map_or(Ok(()), |val| {
289                    if val.is_integer() {
290                        write!(f, "> {val}")
291                    } else {
292                        // If the prime factors of the denominator are only 2 and 5,
293                        // then the number requires a finite number of digits and thus
294                        // will be represented perfectly using the fewest number of digits.
295                        // Any other situation will be rounded to 9 fractional digits.
296                        // max{twos, fives} represents the minimum number of fractional
297                        // digits necessary to represent val.
298                        let mut twos = 0;
299                        let mut fives = 0;
300                        let zero = BigInt::from_biguint(Sign::NoSign, BigUint::new(Vec::new()));
301                        let one = BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1]));
302                        let two = BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]));
303                        let five = BigInt::from_biguint(Sign::Plus, BigUint::new(vec![5]));
304                        let mut denom = val.denom().clone();
305                        let mut div_rem;
306                        while denom > one {
307                            div_rem = denom.div_rem(&two);
308                            if div_rem.1 == zero {
309                                twos += 1;
310                                denom = div_rem.0;
311                            } else {
312                                break;
313                            }
314                        }
315                        while denom > one {
316                            div_rem = denom.div_rem(&five);
317                            if div_rem.1 == zero {
318                                fives += 1;
319                                denom = div_rem.0;
320                            } else {
321                                break;
322                            }
323                        }
324                        // int < 0 iff val <= -1. frac < 0 iff val is a negative non-integer.
325                        let (int, frac, digits) = if denom == one {
326                            let (int, mut frac) = val.numer().div_rem(val.denom());
327                            while twos > fives {
328                                frac *= &five;
329                                fives += 1;
330                            }
331                            while fives > twos {
332                                frac *= &two;
333                                twos += 1;
334                            }
335                            (int, frac, twos)
336                        } else {
337                            // Requires an infinite number of decimal digits to represent, so we display
338                            // 9 digits after rounding.
339                            let mult =
340                                BigInt::from_biguint(Sign::Plus, BigUint::new(vec![10])).pow(9u8);
341                            let (int, frac) = (val * &mult).round().numer().div_rem(&mult);
342                            (int, frac, 9)
343                        };
344                        let int_str = int.to_string().into_bytes();
345                        let (mut v, frac_str) = if val.numer().sign() == Sign::Minus {
346                            // Guaranteed to be non-empty.
347                            if int_str[0] == b'-' {
348                                (
349                                    Vec::with_capacity(int_str.len() + 1 + digits),
350                                    (-frac).to_string().into_bytes(),
351                                )
352                            } else {
353                                let mut tmp = Vec::with_capacity(int_str.len() + 2 + digits);
354                                tmp.push(b'-');
355                                (tmp, (-frac).to_string().into_bytes())
356                            }
357                        } else {
358                            (
359                                Vec::with_capacity(int_str.len() + 1 + digits),
360                                frac.to_string().into_bytes(),
361                            )
362                        };
363                        v.extend_from_slice(int_str.as_slice());
364                        v.push(b'.');
365                        // digits >= frac_str.len().
366                        v.resize(v.len() + (digits - frac_str.len()), b'0');
367                        v.extend_from_slice(frac_str.as_slice());
368                        // SAFETY:
369                        // v contains precisely the UTF-8 code units returned from Strings
370                        // returned from the to_string function on the integer and fraction part of
371                        // val plus optionally the single byte encodings of ".", "-", and "0".
372                        write!(f, "> {}", unsafe { String::from_utf8_unchecked(v) })
373                    }
374                })
375            }
376            Eval(r) => write!(f, "> {r}"),
377            Exit => Ok(()),
378            Store(o) => o.as_ref().map_or(Ok(()), |val| write!(f, "> {val}")),
379        }
380    }
381}
382/// Size of [`Evaluator::cache`].
383const CACHE_SIZE: usize = 8;
384/// Evaluates the supplied input.
385pub struct Evaluator<'input, 'cache, 'prev, 'scratch, 'rand> {
386    /// The input to be evaluated.
387    utf8: &'input [u8],
388    /// The index within `utf8` that evaluation needs to continue.
389    /// We use this instead of slicing from `utf8` since we want
390    /// to be able to report the position within the input
391    /// that an error occurs.
392    i: usize,
393    /// The cache of previously stored results.
394    cache: &'cache mut Cache<Ratio<BigInt>, CACHE_SIZE>,
395    /// The last result.
396    prev: &'prev mut Option<Ratio<BigInt>>,
397    /// Buffer used to evaluate right-associative sub-expressions.
398    scratch: &'scratch mut Vec<Ratio<BigInt>>,
399    /// Random number generator.
400    #[cfg(feature = "rand")]
401    rng: &'rand mut ThreadRng,
402    #[cfg(not(feature = "rand"))]
403    _rng: PhantomData<fn() -> &'rand ()>,
404}
405#[allow(
406    clippy::allow_attributes,
407    clippy::elidable_lifetime_names,
408    reason = "unify rand and not rand"
409)]
410impl<'input, 'cache, 'prev, 'scratch, 'rand> Evaluator<'input, 'cache, 'prev, 'scratch, 'rand> {
411    /// Creates an `Evaluator<'input, 'cache, 'prev, 'scratch, 'rand>` based on the supplied arguments.
412    #[cfg(not(feature = "rand"))]
413    #[inline]
414    pub fn new(
415        utf8: &'input [u8],
416        cache: &'cache mut Cache<Ratio<BigInt>, 8>,
417        prev: &'prev mut Option<Ratio<BigInt>>,
418        scratch: &'scratch mut Vec<Ratio<BigInt>>,
419    ) -> Self {
420        Self {
421            utf8,
422            i: 0,
423            cache,
424            prev,
425            scratch,
426            _rng: PhantomData,
427        }
428    }
429    /// Creates an `Evaluator<'input, 'cache, 'prev, 'scratch, 'rand>` based on the supplied arguments.
430    #[cfg(feature = "rand")]
431    #[inline]
432    pub const fn new(
433        utf8: &'input [u8],
434        cache: &'cache mut Cache<Ratio<BigInt>, 8>,
435        prev: &'prev mut Option<Ratio<BigInt>>,
436        scratch: &'scratch mut Vec<Ratio<BigInt>>,
437        rng: &'rand mut ThreadRng,
438    ) -> Self {
439        Self {
440            utf8,
441            i: 0,
442            cache,
443            prev,
444            scratch,
445            rng,
446        }
447    }
448    /// Evaluates the input consuming the `Evaluator<'input, 'cache, 'exp>`.
449    ///
450    /// Requires the input to contain one expression (i.e., if there are
451    /// multiple newlines, it will error).
452    ///
453    /// # Errors
454    ///
455    /// Returns a [`LangErr`] iff the input violates the calc language.
456    #[expect(clippy::indexing_slicing, reason = "correct")]
457    #[inline]
458    pub fn evaluate(mut self) -> Result<O<'prev>, LangErr> {
459        self.utf8 = if self.utf8.last().is_none_or(|b| *b != b'\n') {
460            self.utf8
461        } else {
462            &self.utf8[..self.utf8.len()
463                - self
464                    .utf8
465                    .get(self.utf8.len().wrapping_sub(2))
466                    .map_or(1, |b| if *b == b'\r' { 2 } else { 1 })]
467        };
468        self.consume_ws();
469        let Some(b) = self.utf8.get(self.i) else {
470            return Ok(Empty(self.prev));
471        };
472        if *b == b'q' {
473            self.i += 1;
474            self.consume_ws();
475            if self.i == self.utf8.len() {
476                Ok(Exit)
477            } else {
478                Err(InvalidQuit)
479            }
480        } else if *b == b's' {
481            self.i += 1;
482            self.consume_ws();
483            if self.i == self.utf8.len() {
484                if let Some(ref val) = *self.prev {
485                    self.cache.push(val.clone());
486                }
487                Ok(Store(self.prev))
488            } else {
489                Err(InvalidStore)
490            }
491        } else {
492            self.get_adds().and_then(move |val| {
493                self.consume_ws();
494                if self.i == self.utf8.len() {
495                    Ok(Eval(self.prev.insert(val)))
496                } else {
497                    Err(TrailingSyms(self.i))
498                }
499            })
500        }
501    }
502    /// Reads from the input until the next non-{space/tab} byte value.
503    #[expect(clippy::indexing_slicing, reason = "correct")]
504    fn consume_ws(&mut self) {
505        // ControlFlow makes more sense to use in try_fold; however due to a lack
506        // of a map_or_else function, it is easier to simply return a Result with
507        // Err taking the role of ControlFlow::Break.
508        self.i += self.utf8[self.i..]
509            .iter()
510            .try_fold(0, |val, b| match *b {
511                b' ' | b'\t' => Ok(val + 1),
512                _ => Err(val),
513            })
514            .map_or_else(convert::identity, convert::identity);
515    }
516    /// Evaluates addition expressions as defined in the calc language.
517    /// This function is used for both addition and subtraction operations which
518    /// themselves are based on multiplication expressions.
519    fn get_adds(&mut self) -> Result<Ratio<BigInt>, LangErr> {
520        let mut left = self.get_mults()?;
521        let mut j;
522        self.consume_ws();
523        while let Some(i) = self.utf8.get(self.i) {
524            j = *i;
525            self.consume_ws();
526            if j == b'+' {
527                self.i += 1;
528                self.consume_ws();
529                left += self.get_mults()?;
530            } else if j == b'-' {
531                self.i += 1;
532                self.consume_ws();
533                left -= self.get_mults()?;
534            } else {
535                break;
536            }
537        }
538        Ok(left)
539    }
540    /// Evaluates multiplication expressions as defined in the calc language.
541    /// This function is used for both multiplication and division operations which
542    /// themselves are based on negation expressions.
543    fn get_mults(&mut self) -> Result<Ratio<BigInt>, LangErr> {
544        let mut left = self.get_neg()?;
545        let mut right;
546        let mut j;
547        let mut mod_val;
548        let mut numer;
549        self.consume_ws();
550        while let Some(i) = self.utf8.get(self.i) {
551            j = *i;
552            self.consume_ws();
553            if j == b'*' {
554                self.i += 1;
555                self.consume_ws();
556                left *= self.get_neg()?;
557            } else if j == b'/' {
558                self.i += 1;
559                self.consume_ws();
560                right = self.get_neg()?;
561                if right.numer().sign() == Sign::NoSign {
562                    return Err(DivByZero(self.i));
563                }
564                left /= right;
565            } else if let Some(k) = self.utf8.get(self.i..self.i.saturating_add(3)) {
566                if k == b"mod" {
567                    if !left.is_integer() {
568                        return Err(ModIsNotInt(self.i));
569                    }
570                    self.i += 3;
571                    self.consume_ws();
572                    right = self.get_neg()?;
573                    if !right.is_integer() {
574                        return Err(ModIsNotInt(self.i));
575                    }
576                    numer = right.numer();
577                    if numer.sign() == Sign::NoSign {
578                        return Err(ModZero(self.i));
579                    }
580                    mod_val = left.numer() % numer;
581                    left = Ratio::from_integer(if mod_val.sign() == Sign::Minus {
582                        if numer.sign() == Sign::Minus {
583                            mod_val - numer
584                        } else {
585                            mod_val + numer
586                        }
587                    } else {
588                        mod_val
589                    });
590                } else {
591                    break;
592                }
593            } else {
594                break;
595            }
596        }
597        Ok(left)
598    }
599    /// Evaluates negation expressions as defined in the calc language.
600    /// This function is based on exponentiation expressions.
601    fn get_neg(&mut self) -> Result<Ratio<BigInt>, LangErr> {
602        let mut count = 0usize;
603        while let Some(b) = self.utf8.get(self.i) {
604            if *b == b'-' {
605                self.i += 1;
606                self.consume_ws();
607                count += 1;
608            } else {
609                break;
610            }
611        }
612        self.get_exps()
613            .map(|val| if count & 1 == 0 { val } else { -val })
614    }
615    /// Gets the square root of value so long as a solution exists.
616    #[expect(
617        clippy::unreachable,
618        reason = "code that shouldn't happen did, so we want to crash"
619    )]
620    fn sqrt(val: Ratio<BigInt>) -> Option<Ratio<BigInt>> {
621        /// Returns the square root of `n` if one exists; otherwise
622        /// returns `None`.
623        /// MUST NOT pass 0.
624        #[expect(clippy::suspicious_operation_groupings, reason = "false positive")]
625        fn calc(n: &BigUint) -> Option<BigUint> {
626            let mut shift = n.bits();
627            shift += shift & 1;
628            let mut result = BigUint::new(Vec::new());
629            let one = BigUint::new(vec![1]);
630            let zero = BigUint::new(Vec::new());
631            loop {
632                shift -= 2;
633                result <<= 1u32;
634                result |= &one;
635                result ^= if &result * &result > (n >> shift) {
636                    &one
637                } else {
638                    &zero
639                };
640                if shift == 0 {
641                    break (&result * &result == *n).then_some(result);
642                }
643            }
644        }
645        let numer = val.numer();
646        if numer.sign() == Sign::NoSign {
647            Some(val)
648        } else {
649            numer.try_into().map_or_else(
650                |_| None,
651                |num| {
652                    calc(&num).and_then(|n| {
653                        calc(&val.denom().try_into().unwrap_or_else(|_| {
654                            unreachable!("Ratio must never have a negative denominator")
655                        }))
656                        .map(|d| Ratio::new(n.into(), d.into()))
657                    })
658                },
659            )
660        }
661    }
662    /// Evaluates exponentiation expressions as defined in the calc language.
663    /// This function is based on negation expressions.
664    fn get_exps(&mut self) -> Result<Ratio<BigInt>, LangErr> {
665        let mut t = self.get_fact()?;
666        let ix = self.scratch.len();
667        let mut prev;
668        let mut numer;
669        self.scratch.push(t);
670        self.consume_ws();
671        let mut j;
672        let one = BigInt::new(Sign::Plus, vec![1]);
673        let min_one = BigInt::new(Sign::Minus, vec![1]);
674        let two = BigInt::new(Sign::Plus, vec![2]);
675        while let Some(i) = self.utf8.get(self.i) {
676            j = *i;
677            self.consume_ws();
678            if j == b'^' {
679                self.i += 1;
680                self.consume_ws();
681                t = self.get_neg()?;
682                // Safe since we always push at least one value, and we always
683                // return immediately once we encounter an error.
684                prev = self.scratch.index(self.scratch.len() - 1);
685                numer = prev.numer();
686                // Equiv to checking if prev is 0.
687                if numer.sign() == Sign::NoSign {
688                    if t.numer().sign() == Sign::Minus {
689                        self.scratch.clear();
690                        return Err(ExpDivByZero(self.i));
691                    }
692                    self.scratch.push(t);
693                } else if prev.is_integer() {
694                    let t_numer = t.numer();
695                    // 1 raised to anything is 1, so we don't bother
696                    // storing the exponent.
697                    if *numer == one {
698                    } else if t.is_integer()
699                        || ((*t_numer == one || *t_numer == min_one) && *t.denom() == two)
700                    {
701                        self.scratch.push(t);
702                    } else {
703                        self.scratch.clear();
704                        return Err(ExpIsNotIntOrOneHalf(self.i));
705                    }
706                } else if t.is_integer()
707                    || ((*t.numer() == one || *t.numer() == min_one) && *t.denom() == two)
708                {
709                    self.scratch.push(t);
710                } else {
711                    self.scratch.clear();
712                    return Err(ExpIsNotIntOrOneHalf(self.i));
713                }
714            } else {
715                break;
716            }
717        }
718        self.scratch
719            .drain(ix..)
720            .try_rfold(Ratio::from_integer(one.clone()), |exp, base| {
721                if exp.is_integer() {
722                    Ok(base.pow(exp.numer()))
723                } else if base.numer().sign() == Sign::NoSign {
724                    Ok(base)
725                } else if *exp.denom() == two {
726                    if *exp.numer() == one {
727                        Self::sqrt(base).map_or_else(|| Err(SqrtDoesNotExist(self.i)), Ok)
728                    } else if *exp.numer() == min_one {
729                        Self::sqrt(base)
730                            .map_or_else(|| Err(SqrtDoesNotExist(self.i)), |v| Ok(v.inv()))
731                    } else {
732                        Err(ExpIsNotIntOrOneHalf(self.i))
733                    }
734                } else {
735                    Err(ExpIsNotIntOrOneHalf(self.i))
736                }
737            })
738    }
739    /// Evaluates factorial expressions as defined in the calc language.
740    /// This function is based on terminal expressions.
741    fn get_fact(&mut self) -> Result<Ratio<BigInt>, LangErr> {
742        /// Calculates the factorial of `val`.
743        fn fact(mut val: BigUint) -> BigUint {
744            let zero = BigUint::new(Vec::new());
745            let one = BigUint::new(vec![1]);
746            let mut calc = BigUint::new(vec![1]);
747            while val > zero {
748                calc *= &val;
749                val -= &one;
750            }
751            calc
752        }
753        let t = self.get_term()?;
754        let Some(b) = self.utf8.get(self.i) else {
755            return Ok(t);
756        };
757        if *b == b'!' {
758            self.i += 1;
759            if t.is_integer() {
760                // We can make a copy of self.i here, or call map_or instead
761                // of map_or_else.
762                let i = self.i;
763                t.numer().try_into().map_or_else(
764                    |_| Err(NotNonNegIntFact(i)),
765                    |val| {
766                        let mut factorial = fact(val);
767                        while let Some(b2) = self.utf8.get(self.i) {
768                            if *b2 == b'!' {
769                                self.i += 1;
770                                factorial = fact(factorial);
771                            } else {
772                                break;
773                            }
774                        }
775                        Ok(Ratio::from_integer(BigInt::from_biguint(
776                            Sign::Plus,
777                            factorial,
778                        )))
779                    },
780                )
781            } else {
782                Err(NotNonNegIntFact(self.i))
783            }
784        } else {
785            Ok(t)
786        }
787    }
788    /// Evaluates terminal expressions as defined in the calc language.
789    /// This function is based on number literal expressions, parenthetical expressions,
790    /// recall expressions, absolute value expressions, round expressions, and possibly
791    /// rand expressions if that feature is enabled.
792    fn get_term(&mut self) -> Result<Ratio<BigInt>, LangErr> {
793        self.get_rational().map_or_else(Err, |o| {
794            o.map_or_else(
795                || {
796                    self.get_par().map_or_else(Err, |o2| {
797                        o2.map_or_else(
798                            || {
799                                self.get_recall().map_or_else(Err, |o3| {
800                                    o3.map_or_else(
801                                        || {
802                                            self.get_abs().map_or_else(Err, |o4| {
803                                                o4.map_or_else(
804                                                    || {
805                                                        self.get_round().and_then(|o5| {
806                                                            o5.map_or_else(
807                                                                #[cfg(not(feature = "rand"))]
808                                                                || Err(MissingTerm(self.i)),
809                                                                #[cfg(feature = "rand")]
810                                                                || self.get_rand(),
811                                                                Ok,
812                                                            )
813                                                        })
814                                                    },
815                                                    Ok,
816                                                )
817                                            })
818                                        },
819                                        Ok,
820                                    )
821                                })
822                            },
823                            Ok,
824                        )
825                    })
826                },
827                Ok,
828            )
829        })
830    }
831    /// Generates a random 64-bit integer. This function is based on add expressions. This is the last terminal
832    /// expression attempted when needing a terminal expression; as a result, it is the only terminal expression
833    /// that does not return an `Option`.
834    #[cfg(feature = "rand")]
835    fn get_rand(&mut self) -> Result<Ratio<BigInt>, LangErr> {
836        /// Generates a random 64-bit integer.
837        #[expect(clippy::host_endian_bytes, reason = "must keep platform endianness")]
838        fn rand(rng: &mut ThreadRng) -> i64 {
839            let mut bytes = [0; 8];
840            // `ThreadRng::try_fill_bytes` is infallible, so easier to call `fill_bytes`.
841            rng.fill_bytes(&mut bytes);
842            i64::from_ne_bytes(bytes)
843        }
844        /// Generates a random 64-bit integer inclusively between the passed arguments.
845        #[expect(
846            clippy::integer_division_remainder_used,
847            reason = "need for uniform randomness"
848        )]
849        #[expect(
850            clippy::as_conversions,
851            clippy::cast_possible_truncation,
852            clippy::cast_possible_wrap,
853            clippy::cast_sign_loss,
854            reason = "lossless conversions between signed integers"
855        )]
856        fn rand_range(
857            rng: &mut ThreadRng,
858            lower: &Ratio<BigInt>,
859            upper: &Ratio<BigInt>,
860            i: usize,
861        ) -> Result<i64, LangErr> {
862            if lower > upper {
863                return Err(LangErr::RandInvalidArgs(i));
864            }
865            let lo = lower.ceil();
866            let up = upper.floor();
867            let lo_int = lo.numer();
868            let up_int = up.numer();
869            if lo_int > &BigInt::from(i64::MAX) || up_int < &BigInt::from(i64::MIN) {
870                return Err(LangErr::RandNoInts(i));
871            }
872            let lo_min = lo_int.to_i64().unwrap_or(i64::MIN);
873            let up_max = up_int.to_i64().unwrap_or(i64::MAX);
874            if up_max > lo_min || upper.is_integer() || lower.is_integer() {
875                let low = i128::from(lo_min);
876                // `i64::MAX >= up_max >= low`; so underflow and overflow cannot happen.
877                // range is [1, 2^64] so casting to a u128 is fine.
878                let modulus = (i128::from(up_max) - low + 1) as u128;
879                // range is [0, i64::MAX] so converting to a `u64` is fine.
880                // rem represents how many values need to be removed
881                // when generating a random i64 in order for uniformity.
882                let rem = (0x0001_0000_0000_0000_0000 % modulus) as u64;
883                let mut low_adj;
884                loop {
885                    low_adj = rand(rng) as u64;
886                    // Since rem is in [0, i64::MAX], this is the same as low_adj < 0 || low_adj >= rem.
887                    if low_adj >= rem {
888                        return Ok(
889                            // range is [i64::MIN, i64::MAX]; thus casts are safe.
890                            // modulus is up_max - low + 1; so as low grows,
891                            // % shrinks by the same factor. i64::MAX happens
892                            // when low = up_max = i64::MAX or when low = 0,
893                            // up_max = i64::MAX and low_adj is i64::MAX.
894                            ((u128::from(low_adj) % modulus) as i128 + low) as i64,
895                        );
896                    }
897                }
898            } else {
899                Err(LangErr::RandNoInts(i))
900            }
901        }
902        // This is the last kind of terminal expression that is attempted.
903        // If there is no more data, then we have a missing terminal expression.
904        let Some(b) = self.utf8.get(self.i..self.i.saturating_add(5)) else {
905            return Err(MissingTerm(self.i));
906        };
907        if b == b"rand(" {
908            self.i += 5;
909            self.consume_ws();
910            let i = self.i;
911            self.utf8.get(self.i).map_or_else(
912                || Err(LangErr::InvalidRand(i)),
913                |p| {
914                    if *p == b')' {
915                        self.i += 1;
916                        Ok(Ratio::from_integer(BigInt::from(rand(self.rng))))
917                    } else {
918                        let add = self.get_adds()?;
919                        let Some(b2) = self.utf8.get(self.i) else {
920                            return Err(LangErr::InvalidRand(self.i));
921                        };
922                        if *b2 == b',' {
923                            self.i += 1;
924                            self.consume_ws();
925                            let add2 = self.get_adds()?;
926                            self.consume_ws();
927                            let Some(b3) = self.utf8.get(self.i) else {
928                                return Err(LangErr::InvalidRand(self.i));
929                            };
930                            if *b3 == b')' {
931                                self.i += 1;
932                                rand_range(self.rng, &add, &add2, self.i)
933                                    .map(|v| Ratio::from_integer(BigInt::from(v)))
934                            } else {
935                                Err(LangErr::InvalidRand(self.i))
936                            }
937                        } else {
938                            Err(LangErr::InvalidRand(self.i))
939                        }
940                    }
941                },
942            )
943        } else {
944            Err(MissingTerm(self.i))
945        }
946    }
947    /// Rounds a value to the specified number of fractional digits.
948    /// This function is based on add expressions.
949    fn get_round(&mut self) -> Result<Option<Ratio<BigInt>>, LangErr> {
950        let Some(b) = self.utf8.get(self.i..self.i.saturating_add(6)) else {
951            return Ok(None);
952        };
953        if b == b"round(" {
954            self.i += 6;
955            self.consume_ws();
956            let val = self.get_adds()?;
957            self.consume_ws();
958            let Some(b2) = self.utf8.get(self.i) else {
959                return Err(InvalidRound(self.i));
960            };
961            let b3 = *b2;
962            if b3 == b',' {
963                self.i += 1;
964                self.consume_ws();
965                let Some(b4) = self.utf8.get(self.i) else {
966                    return Err(InvalidRound(self.i));
967                };
968                let r = if b4.is_ascii_digit() {
969                    self.i += 1;
970                    *b4 - b'0'
971                } else {
972                    return Err(InvalidRound(self.i));
973                };
974                self.consume_ws();
975                let i = self.i;
976                self.utf8.get(self.i).map_or_else(
977                    || Err(InvalidRound(i)),
978                    |p| {
979                        if *p == b')' {
980                            self.i += 1;
981                            let mult =
982                                BigInt::from_biguint(Sign::Plus, BigUint::new(vec![10])).pow(r);
983                            Ok(Some((val * &mult).round() / &mult))
984                        } else {
985                            Err(InvalidRound(self.i))
986                        }
987                    },
988                )
989            } else {
990                Err(InvalidRound(self.i))
991            }
992        } else {
993            Ok(None)
994        }
995    }
996    /// Evaluates absolute value expressions as defined in the calc language.
997    /// This function is based on add expressions.
998    fn get_abs(&mut self) -> Result<Option<Ratio<BigInt>>, LangErr> {
999        let Some(b) = self.utf8.get(self.i) else {
1000            return Ok(None);
1001        };
1002        if *b == b'|' {
1003            self.i += 1;
1004            self.consume_ws();
1005            let r = self.get_adds()?;
1006            self.consume_ws();
1007            let Some(b2) = self.utf8.get(self.i) else {
1008                return Err(InvalidAbs(self.i));
1009            };
1010            let b3 = *b2;
1011            if b3 == b'|' {
1012                self.i += 1;
1013                Ok(Some(if r.numer().sign() == Sign::Minus {
1014                    -r
1015                } else {
1016                    r
1017                }))
1018            } else {
1019                Err(InvalidAbs(self.i))
1020            }
1021        } else {
1022            Ok(None)
1023        }
1024    }
1025    /// Evaluates recall expressions as defined in the calc language.
1026    // This does not return a Result<Option<&Ratio<BigInt>>, LangErr>
1027    // since the only place this function is called is in get_term which
1028    // would end up needing to clone the Ratio anyway. By not forcing
1029    // get_term to clone, it can rely on map_or_else over match expressions.
1030    fn get_recall(&mut self) -> Result<Option<Ratio<BigInt>>, LangErr> {
1031        let Some(b) = self.utf8.get(self.i) else {
1032            return Ok(None);
1033        };
1034        if *b == b'@' {
1035            self.i += 1;
1036            self.cache
1037                .get(self.utf8.get(self.i).map_or(0, |b2| {
1038                    if (b'1'..b'9').contains(b2) {
1039                        self.i += 1;
1040                        usize::from(*b2 - b'1')
1041                    } else {
1042                        0
1043                    }
1044                }))
1045                .map_or_else(
1046                    || Err(NotEnoughPrevResults(self.cache.len())),
1047                    |p| Ok(Some(p.clone())),
1048                )
1049        } else {
1050            Ok(None)
1051        }
1052    }
1053    /// Evaluates parenthetical expressions as defined in the calc language.
1054    /// This function is based on add expressions.
1055    fn get_par(&mut self) -> Result<Option<Ratio<BigInt>>, LangErr> {
1056        let Some(b) = self.utf8.get(self.i) else {
1057            return Ok(None);
1058        };
1059        if *b == b'(' {
1060            self.i += 1;
1061            self.consume_ws();
1062            let r = self.get_adds()?;
1063            self.consume_ws();
1064            let Some(b2) = self.utf8.get(self.i) else {
1065                return Err(InvalidPar(self.i));
1066            };
1067            let b3 = *b2;
1068            if b3 == b')' {
1069                self.i += 1;
1070                Ok(Some(r))
1071            } else {
1072                Err(InvalidPar(self.i))
1073            }
1074        } else {
1075            Ok(None)
1076        }
1077    }
1078    /// Evaluates number literal expressions as defined in the calc language.
1079    #[expect(clippy::indexing_slicing, reason = "correct")]
1080    fn get_rational(&mut self) -> Result<Option<Ratio<BigInt>>, LangErr> {
1081        // ControlFlow makes more sense to use in try_fold; however due to a lack
1082        // of a map_or_else function, it is easier to simply return a Result with
1083        // Err taking the role of ControlFlow::Break.
1084        /// Used to parse a sequence of digits into an unsigned integer.
1085        fn to_biguint(v: &[u8]) -> (BigUint, usize) {
1086            v.iter()
1087                .try_fold((BigUint::new(Vec::new()), 0), |mut prev, d| {
1088                    if d.is_ascii_digit() {
1089                        prev.1 += 1;
1090                        // `*d - b'0'` is guaranteed to return a integer between 0 and 9.
1091                        prev.0 = prev.0 * 10u8 + (*d - b'0');
1092                        Ok(prev)
1093                    } else {
1094                        Err(prev)
1095                    }
1096                })
1097                .map_or_else(convert::identity, convert::identity)
1098        }
1099        let (int, len) = to_biguint(&self.utf8[self.i..]);
1100        if len == 0 {
1101            return Ok(None);
1102        }
1103        self.i += len;
1104        if let Some(b) = self.utf8.get(self.i) {
1105            if *b == b'.' {
1106                self.i += 1;
1107                let (numer, len2) = to_biguint(&self.utf8[self.i..]);
1108                if len2 == 0 {
1109                    Err(InvalidDec(self.i))
1110                } else {
1111                    self.i += len2;
1112                    Ok(Some(
1113                        Ratio::from_integer(BigInt::from_biguint(Sign::Plus, int))
1114                            + Ratio::new(
1115                                BigInt::from_biguint(Sign::Plus, numer),
1116                                BigInt::from_biguint(Sign::Plus, BigUint::new(vec![10]).pow(len2)),
1117                            ),
1118                    ))
1119                }
1120            } else {
1121                Ok(Some(Ratio::from_integer(BigInt::from_biguint(
1122                    Sign::Plus,
1123                    int,
1124                ))))
1125            }
1126        } else {
1127            Ok(Some(Ratio::from_integer(BigInt::from_biguint(
1128                Sign::Plus,
1129                int,
1130            ))))
1131        }
1132    }
1133}
1134/// Reads data from `R` passing each line to an [`Evaluator`] to be evaluated.
1135#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1136#[cfg(feature = "std")]
1137pub struct EvalIter<R> {
1138    /// Reader that contains input data.
1139    reader: R,
1140    /// Buffer that is used by `reader` to read
1141    /// data into.
1142    input_buffer: Vec<u8>,
1143    /// Cache of stored results.
1144    cache: Cache<Ratio<BigInt>, 8>,
1145    /// Result of the previous expression.
1146    prev: Option<Ratio<BigInt>>,
1147    /// Buffer used by [`Evaluator`] to process
1148    /// sub-expressions.
1149    exp_buffer: Vec<Ratio<BigInt>>,
1150    /// Random number generator.
1151    #[cfg(feature = "rand")]
1152    rng: ThreadRng,
1153}
1154#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1155#[cfg(feature = "std")]
1156impl<R> EvalIter<R> {
1157    /// Creates a new `EvalIter`.
1158    #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
1159    #[cfg(feature = "rand")]
1160    #[inline]
1161    pub fn new(reader: R) -> Self {
1162        Self {
1163            reader,
1164            input_buffer: Vec::new(),
1165            cache: Cache::new(),
1166            prev: None,
1167            exp_buffer: Vec::new(),
1168            rng: rand::rng(),
1169        }
1170    }
1171    /// Creates a new `EvalIter`.
1172    #[cfg(any(doc, not(feature = "rand")))]
1173    #[inline]
1174    pub fn new(reader: R) -> Self {
1175        Self {
1176            reader,
1177            input_buffer: Vec::new(),
1178            cache: Cache::new(),
1179            prev: None,
1180            exp_buffer: Vec::new(),
1181        }
1182    }
1183}
1184#[cfg(feature = "std")]
1185extern crate std;
1186#[cfg(feature = "std")]
1187use std::io::{BufRead, Error};
1188/// Error returned from [`EvalIter`] when an expression has an error.
1189#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1190#[cfg(feature = "std")]
1191#[derive(Debug)]
1192pub enum E {
1193    /// Error containing [`Error`] which is returned
1194    /// from [`EvalIter`] when reading from the supplied
1195    /// [`BufRead`]er.
1196    Error(Error),
1197    /// Error containing [`LangErr`] which is returned
1198    /// from [`EvalIter`] when evaluating a single expression.
1199    LangErr(LangErr),
1200}
1201#[cfg(feature = "std")]
1202impl Display for E {
1203    #[inline]
1204    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1205        match *self {
1206            Self::Error(ref e) => e.fmt(f),
1207            Self::LangErr(ref e) => e.fmt(f),
1208        }
1209    }
1210}
1211#[cfg(feature = "std")]
1212use crate::lending_iterator::LendingIterator;
1213#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1214#[cfg(feature = "std")]
1215impl<R> LendingIterator for EvalIter<R>
1216where
1217    R: BufRead,
1218{
1219    type Item<'a>
1220        = Result<O<'a>, E>
1221    where
1222        Self: 'a;
1223    #[inline]
1224    fn lend_next(&mut self) -> Option<Result<O<'_>, E>> {
1225        self.input_buffer.clear();
1226        self.exp_buffer.clear();
1227        self.reader
1228            .read_until(b'\n', &mut self.input_buffer)
1229            .map_or_else(
1230                |e| Some(Err(E::Error(e))),
1231                |c| {
1232                    if c == 0 {
1233                        None
1234                    } else {
1235                        Evaluator::new(
1236                            self.input_buffer.as_slice(),
1237                            &mut self.cache,
1238                            &mut self.prev,
1239                            &mut self.exp_buffer,
1240                            #[cfg(feature = "rand")]
1241                            &mut self.rng,
1242                        )
1243                        .evaluate()
1244                        .map_or_else(
1245                            |e| Some(Err(E::LangErr(e))),
1246                            |o| match o {
1247                                O::Empty(_) | O::Eval(_) | O::Store(_) => Some(Ok(o)),
1248                                O::Exit => None,
1249                            },
1250                        )
1251                    }
1252                },
1253            )
1254    }
1255}
1256#[cfg(test)]
1257mod tests {
1258    use super::*;
1259    #[cfg(not(feature = "rand"))]
1260    #[test]
1261    fn empty() {
1262        // Empty expressions without a previous result return nothing.
1263        assert!(
1264            match Evaluator::new(b"\n", &mut Cache::new(), &mut None, &mut Vec::new())
1265                .evaluate()
1266                .unwrap()
1267            {
1268                O::Empty(o) => o.is_none(),
1269                _ => false,
1270            }
1271        );
1272        assert!(
1273            Evaluator::new(
1274                b"  \t  \t \n",
1275                &mut Cache::new(),
1276                &mut Some(Ratio::from_integer(BigInt::from_biguint(
1277                    Sign::Minus,
1278                    BigUint::new(vec![12])
1279                ))),
1280                &mut Vec::new()
1281            )
1282            .evaluate()
1283            .unwrap()
1284            .to_string()
1285                == "> -12"
1286        );
1287        assert!(
1288            Evaluator::new(
1289                b"\t\n",
1290                &mut Cache::new(),
1291                &mut Some(Ratio::new(
1292                    BigInt::from_biguint(Sign::Minus, BigUint::new(vec![4])),
1293                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![6]))
1294                )),
1295                &mut Vec::new()
1296            )
1297            .evaluate()
1298            .unwrap()
1299            .to_string()
1300                == "> -0.666666667"
1301        );
1302        assert!(
1303            Evaluator::new(
1304                b"\t\n",
1305                &mut Cache::new(),
1306                &mut Some(Ratio::new(
1307                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])),
1308                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4230196224, 6]))
1309                )),
1310                &mut Vec::new()
1311            )
1312            .evaluate()
1313            .unwrap()
1314            .to_string()
1315                == "> 0.000000000"
1316        );
1317        assert!(
1318            Evaluator::new(
1319                b"\t\n",
1320                &mut Cache::new(),
1321                &mut Some(Ratio::new(
1322                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![17])),
1323                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4230196224, 6]))
1324                )),
1325                &mut Vec::new()
1326            )
1327            .evaluate()
1328            .unwrap()
1329            .to_string()
1330                == "> 0.000000001"
1331        );
1332        assert!(
1333            Evaluator::new(
1334                b"\t\n",
1335                &mut Cache::new(),
1336                &mut Some(Ratio::new(
1337                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3])),
1338                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![10]))
1339                )),
1340                &mut Vec::new()
1341            )
1342            .evaluate()
1343            .unwrap()
1344            .to_string()
1345                == "> 0.3"
1346        );
1347        assert!(
1348            Evaluator::new(
1349                b"\t\n",
1350                &mut Cache::new(),
1351                &mut Some(Ratio::new(
1352                    BigInt::from_biguint(Sign::Minus, BigUint::new(vec![203])),
1353                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![10]))
1354                )),
1355                &mut Vec::new()
1356            )
1357            .evaluate()
1358            .unwrap()
1359            .to_string()
1360                == "> -20.3"
1361        );
1362        assert!(
1363            Evaluator::new(
1364                &[0u8; 0],
1365                &mut Cache::new(),
1366                &mut Some(Ratio::new(
1367                    BigInt::from_biguint(Sign::Minus, BigUint::new(vec![203])),
1368                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![10]))
1369                )),
1370                &mut Vec::new()
1371            )
1372            .evaluate()
1373            .unwrap()
1374            .to_string()
1375                == "> -20.3"
1376        );
1377    }
1378    #[cfg(not(feature = "rand"))]
1379    #[test]
1380    fn number_literal() {
1381        // Normal 0 is fine.
1382        assert!(
1383            Evaluator::new(b"0", &mut Cache::new(), &mut None, &mut Vec::new())
1384                .get_rational()
1385                .unwrap()
1386                .unwrap()
1387                == Ratio::from_integer(BigInt::from_biguint(
1388                    Sign::NoSign,
1389                    BigUint::new(Vec::new())
1390                ))
1391        );
1392        // Leading 0s and trailing 0s are fine.
1393        assert!(
1394            Evaluator::new(b"0000.00000", &mut Cache::new(), &mut None, &mut Vec::new())
1395                .get_rational()
1396                .unwrap()
1397                .unwrap()
1398                == Ratio::from_integer(BigInt::from_biguint(
1399                    Sign::NoSign,
1400                    BigUint::new(Vec::new())
1401                ))
1402        );
1403        // Parsing stops at first non-(digit/period).
1404        assert!(
1405            Evaluator::new(b"1 0", &mut Cache::new(), &mut None, &mut Vec::new())
1406                .get_rational()
1407                .unwrap()
1408                .unwrap()
1409                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
1410        );
1411        let int = b"3397450981271938475135134759823759835414";
1412        let frac = b"913759810573549872354897210539127530981570";
1413        let left = Ratio::from_integer(BigInt::parse_bytes(int, 10).unwrap());
1414        let right = Ratio::new(
1415            BigInt::parse_bytes(frac, 10).unwrap(),
1416            BigInt::from_biguint(Sign::Plus, BigUint::new(vec![10]).pow(frac.len() + 1)),
1417        );
1418        let mut vec = Vec::new();
1419        vec.extend_from_slice(int);
1420        vec.push(b'.');
1421        vec.push(b'0');
1422        vec.extend_from_slice(frac);
1423        // Test a number whose integer and fraction portions are larger than u128::MAX.
1424        assert!(
1425            Evaluator::new(
1426                vec.as_slice(),
1427                &mut Cache::new(),
1428                &mut None,
1429                &mut Vec::new()
1430            )
1431            .get_rational()
1432            .unwrap()
1433            .unwrap()
1434                == left + right
1435        );
1436        // Leading 0s and trailing 0s for a non-zero value are fine.
1437        assert!(
1438            Evaluator::new(
1439                b"000000014.0000000000000",
1440                &mut Cache::new(),
1441                &mut None,
1442                &mut Vec::new()
1443            )
1444            .get_rational()
1445            .unwrap()
1446            .unwrap()
1447                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![14])))
1448        );
1449        // A sequence of digits followed immediately by a decimal point but no digits after is invalid.
1450        assert!(
1451            match Evaluator::new(b"1.", &mut Cache::new(), &mut None, &mut Vec::new())
1452                .get_rational()
1453                .unwrap_err()
1454            {
1455                InvalidDec(i) => i == 2,
1456                _ => false,
1457            }
1458        );
1459        // A sequence of digits followed immediately by a decimal point but no digits after is invalid.
1460        // This just shows that spaces are not ignored in number literals.
1461        assert!(
1462            match Evaluator::new(b"1. 2", &mut Cache::new(), &mut None, &mut Vec::new())
1463                .get_rational()
1464                .unwrap_err()
1465            {
1466                InvalidDec(i) => i == 2,
1467                _ => false,
1468            }
1469        );
1470        // Non-whitespace starting the input is valid but produces no value.
1471        // This also shows that an invalid byte sequence does not produce an error here.
1472        assert!(
1473            Evaluator::new(b"a1", &mut Cache::new(), &mut None, &mut Vec::new())
1474                .get_rational()
1475                .unwrap()
1476                .is_none()
1477        );
1478        // A space starting the input is valid but produces no value.
1479        assert!(
1480            Evaluator::new(b" 1", &mut Cache::new(), &mut None, &mut Vec::new())
1481                .get_rational()
1482                .unwrap()
1483                .is_none()
1484        );
1485        // A tab starting the input is valid but produces no value.
1486        assert!(
1487            Evaluator::new(b"\t1", &mut Cache::new(), &mut None, &mut Vec::new())
1488                .get_rational()
1489                .unwrap()
1490                .is_none()
1491        );
1492        // Negative literals don't exist, so this should succeed but produce nothing.
1493        assert!(
1494            Evaluator::new(b"-1", &mut Cache::new(), &mut None, &mut Vec::new())
1495                .get_rational()
1496                .unwrap()
1497                .is_none()
1498        );
1499        // '/' is division and not part of a number literal so only the "numerator" is parsed.
1500        assert!(
1501            Evaluator::new(b"1/2", &mut Cache::new(), &mut None, &mut Vec::new())
1502                .get_rational()
1503                .unwrap()
1504                .unwrap()
1505                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
1506        );
1507        // A sequence of digits followed by invalid bytes is valid and produces a number equal to the digits before the invalid bytes.
1508        assert!(
1509            Evaluator::new(b"130alj", &mut Cache::new(), &mut None, &mut Vec::new())
1510                .get_rational()
1511                .unwrap()
1512                .unwrap()
1513                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![130])))
1514        );
1515    }
1516    #[cfg(not(feature = "rand"))]
1517    #[test]
1518    fn par() {
1519        // Missing closing ')'
1520        assert!(
1521            match Evaluator::new(b"(1", &mut Cache::new(), &mut None, &mut Vec::new())
1522                .get_par()
1523                .unwrap_err()
1524            {
1525                InvalidPar(i) => i == 2,
1526                _ => false,
1527            }
1528        );
1529        assert!(
1530            match Evaluator::new(b"((1\t + 2)", &mut Cache::new(), &mut None, &mut Vec::new())
1531                .get_par()
1532                .unwrap_err()
1533            {
1534                InvalidPar(i) => i == 9,
1535                _ => false,
1536            }
1537        );
1538        assert!(
1539            Evaluator::new(b"(  0 \t )", &mut Cache::new(), &mut None, &mut Vec::new())
1540                .get_par()
1541                .unwrap()
1542                .unwrap()
1543                == Ratio::from_integer(BigInt::from_biguint(
1544                    Sign::NoSign,
1545                    BigUint::new(Vec::new())
1546                ))
1547        );
1548        assert!(
1549            Evaluator::new(b"( - \t 5 )", &mut Cache::new(), &mut None, &mut Vec::new())
1550                .get_par()
1551                .unwrap()
1552                .unwrap()
1553                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![5])))
1554        );
1555        assert!(
1556            Evaluator::new(
1557                b"( ( 2 -\t  5) * 9 )",
1558                &mut Cache::new(),
1559                &mut None,
1560                &mut Vec::new()
1561            )
1562            .get_par()
1563            .unwrap()
1564            .unwrap()
1565                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![27])))
1566        );
1567    }
1568    #[cfg(not(feature = "rand"))]
1569    #[test]
1570    fn recall_expression() {
1571        // If the input does not start with '@', then it's valid but produces nothing.
1572        assert!(
1573            Evaluator::new(b"1", &mut Cache::new(), &mut None, &mut Vec::new())
1574                .get_recall()
1575                .unwrap()
1576                .is_none()
1577        );
1578        assert!(
1579            Evaluator::new(b"a", &mut Cache::new(), &mut None, &mut Vec::new())
1580                .get_recall()
1581                .unwrap()
1582                .is_none()
1583        );
1584        assert!(
1585            Evaluator::new(b" @", &mut Cache::new(), &mut None, &mut Vec::new())
1586                .get_recall()
1587                .unwrap()
1588                .is_none()
1589        );
1590        assert!(
1591            Evaluator::new(b"\t@", &mut Cache::new(), &mut None, &mut Vec::new())
1592                .get_recall()
1593                .unwrap()
1594                .is_none()
1595        );
1596        // Invalid recall expression since there are no previous results.
1597        assert!(
1598            match Evaluator::new(b"@", &mut Cache::new(), &mut None, &mut Vec::new())
1599                .get_recall()
1600                .unwrap_err()
1601            {
1602                NotEnoughPrevResults(count) => count == 0,
1603                _ => false,
1604            }
1605        );
1606        // Invalid recall expression since there are no previous results.
1607        assert!(
1608            match Evaluator::new(b"@4", &mut Cache::new(), &mut None, &mut Vec::new())
1609                .get_recall()
1610                .unwrap_err()
1611            {
1612                NotEnoughPrevResults(count) => count == 0,
1613                _ => false,
1614            }
1615        );
1616        // Invalid recall expression since there are no previous results.
1617        // The input violates our grammar, but this error happens before that.
1618        assert!(
1619            match Evaluator::new(b"@0", &mut Cache::new(), &mut None, &mut Vec::new())
1620                .get_recall()
1621                .unwrap_err()
1622            {
1623                NotEnoughPrevResults(count) => count == 0,
1624                _ => false,
1625            }
1626        );
1627        // Successfully extract previous expression.
1628        let mut prev = None;
1629        let mut cache = Cache::new();
1630        Evaluator::new(b"1\n", &mut cache, &mut prev, &mut Vec::new())
1631            .evaluate()
1632            .unwrap();
1633        Evaluator::new(b"   s   \r\n", &mut cache, &mut prev, &mut Vec::new())
1634            .evaluate()
1635            .unwrap();
1636        assert!(
1637            Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new())
1638                .get_recall()
1639                .unwrap()
1640                .unwrap()
1641                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
1642        );
1643        // Invalid characters are ignored at this stage.
1644        assert!(
1645            Evaluator::new(b"@&", &mut cache, &mut prev, &mut Vec::new())
1646                .get_recall()
1647                .unwrap()
1648                .unwrap()
1649                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
1650        );
1651        // 0 is not a valid stored value only 1-8 are.
1652        assert!(
1653            Evaluator::new(b"@0", &mut cache, &mut prev, &mut Vec::new())
1654                .get_recall()
1655                .unwrap()
1656                .unwrap()
1657                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
1658        );
1659        // 9 is not a valid stored value only 1-8 are.
1660        assert!(
1661            Evaluator::new(b"@9", &mut cache, &mut prev, &mut Vec::new())
1662                .get_recall()
1663                .unwrap()
1664                .unwrap()
1665                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
1666        );
1667        // Spaces are not cleaned; otherwise this would error since we only have 1 stored value.
1668        assert!(
1669            Evaluator::new(b"@ 2", &mut cache, &mut prev, &mut Vec::new())
1670                .get_recall()
1671                .unwrap()
1672                .unwrap()
1673                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
1674        );
1675        // Tabs are not cleaned; otherwise this would error since we only have 1 stored value.
1676        assert!(
1677            Evaluator::new(b"@\t2", &mut cache, &mut prev, &mut Vec::new())
1678                .get_recall()
1679                .unwrap()
1680                .unwrap()
1681                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
1682        );
1683        // One digits are looked at so this is not @<ten>.
1684        assert!(
1685            Evaluator::new(b"@10", &mut cache, &mut prev, &mut Vec::new())
1686                .get_recall()
1687                .unwrap()
1688                .unwrap()
1689                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
1690        );
1691        // Invalid recall expression since there is only one stored result.
1692        assert!(
1693            match Evaluator::new(b"@2", &mut cache, &mut prev, &mut Vec::new())
1694                .get_recall()
1695                .unwrap_err()
1696            {
1697                NotEnoughPrevResults(count) => count == 1,
1698                _ => false,
1699            }
1700        );
1701        Evaluator::new(b"2\r\n", &mut cache, &mut prev, &mut Vec::new())
1702            .evaluate()
1703            .unwrap();
1704        Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
1705            .evaluate()
1706            .unwrap();
1707        // Stored values correct.
1708        assert!(
1709            Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new())
1710                .get_recall()
1711                .unwrap()
1712                .unwrap()
1713                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
1714        );
1715        assert!(
1716            Evaluator::new(b"@2", &mut cache, &mut prev, &mut Vec::new())
1717                .get_recall()
1718                .unwrap()
1719                .unwrap()
1720                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
1721        );
1722        // Invalid recall expression since there are only three stored results.
1723        assert!(
1724            match Evaluator::new(b"@3", &mut cache, &mut prev, &mut Vec::new())
1725                .get_recall()
1726                .unwrap_err()
1727            {
1728                NotEnoughPrevResults(count) => count == 2,
1729                _ => false,
1730            }
1731        );
1732        let mut v = vec![0, b'\n'];
1733        for i in b'3'..=b'8' {
1734            v[0] = i;
1735            Evaluator::new(v.as_slice(), &mut cache, &mut prev, &mut Vec::new())
1736                .evaluate()
1737                .unwrap();
1738            Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
1739                .evaluate()
1740                .unwrap();
1741        }
1742        v[0] = b'@';
1743        for i in b'1'..=b'8' {
1744            v[1] = i;
1745            // Cache is filled up correctly storing all previous values.
1746            assert!(
1747                Evaluator::new(v.as_slice(), &mut cache, &mut prev, &mut Vec::new())
1748                    .get_recall()
1749                    .unwrap()
1750                    .unwrap()
1751                    == Ratio::from_integer(BigInt::from_biguint(
1752                        Sign::Plus,
1753                        BigUint::new(vec![(b'9' - i) as u32])
1754                    ))
1755            );
1756        }
1757        // Only parses the first @ since the second @ is not a digit between 1 and 8.
1758        assert!(
1759            Evaluator::new(b"@@", &mut cache, &mut prev, &mut Vec::new())
1760                .get_recall()
1761                .unwrap()
1762                .unwrap()
1763                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8])))
1764        );
1765        Evaluator::new(b"9\r\n", &mut cache, &mut prev, &mut Vec::new())
1766            .evaluate()
1767            .unwrap();
1768        Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
1769            .evaluate()
1770            .unwrap();
1771        // Oldest value is overwritten; all others remain.
1772        for i in b'1'..=b'8' {
1773            v[1] = i;
1774            assert!(
1775                Evaluator::new(v.as_slice(), &mut cache, &mut prev, &mut Vec::new())
1776                    .get_recall()
1777                    .unwrap()
1778                    .unwrap()
1779                    == Ratio::from_integer(BigInt::from_biguint(
1780                        Sign::Plus,
1781                        BigUint::new(vec![((b'9' + 1) - i) as u32])
1782                    ))
1783            );
1784        }
1785    }
1786    #[cfg(not(feature = "rand"))]
1787    #[test]
1788    fn abs() {
1789        // Missing closing '|'
1790        assert!(
1791            match Evaluator::new(b"|1", &mut Cache::new(), &mut None, &mut Vec::new())
1792                .get_abs()
1793                .unwrap_err()
1794            {
1795                InvalidAbs(i) => i == 2,
1796                _ => false,
1797            }
1798        );
1799        assert!(
1800            match Evaluator::new(b"||1 + 2|", &mut Cache::new(), &mut None, &mut Vec::new())
1801                .get_abs()
1802                .unwrap_err()
1803            {
1804                InvalidAbs(i) => i == 8,
1805                _ => false,
1806            }
1807        );
1808        assert!(
1809            Evaluator::new(
1810                b"|  0\t \t |",
1811                &mut Cache::new(),
1812                &mut None,
1813                &mut Vec::new()
1814            )
1815            .get_abs()
1816            .unwrap()
1817            .unwrap()
1818                == Ratio::from_integer(BigInt::from_biguint(
1819                    Sign::NoSign,
1820                    BigUint::new(Vec::new())
1821                ))
1822        );
1823        assert!(
1824            Evaluator::new(b"| -  5 |", &mut Cache::new(), &mut None, &mut Vec::new())
1825                .get_abs()
1826                .unwrap()
1827                .unwrap()
1828                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![5])))
1829        );
1830        assert!(
1831            Evaluator::new(
1832                b"| \t| 2 -  5| * 9 |",
1833                &mut Cache::new(),
1834                &mut None,
1835                &mut Vec::new()
1836            )
1837            .get_abs()
1838            .unwrap()
1839            .unwrap()
1840                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![27])))
1841        );
1842        // If the input does not start with '|', then it's valid but produces nothing.
1843        assert!(
1844            Evaluator::new(b" \t|9|", &mut Cache::new(), &mut None, &mut Vec::new())
1845                .get_abs()
1846                .unwrap()
1847                .is_none()
1848        );
1849    }
1850    #[cfg(not(feature = "rand"))]
1851    #[test]
1852    fn round() {
1853        // Missing ',<digit>)'
1854        assert!(
1855            match Evaluator::new(b"round(1", &mut Cache::new(), &mut None, &mut Vec::new())
1856                .get_round()
1857                .unwrap_err()
1858            {
1859                InvalidRound(i) => i == 7,
1860                _ => false,
1861            }
1862        );
1863        assert!(
1864            match Evaluator::new(b"round(1,", &mut Cache::new(), &mut None, &mut Vec::new())
1865                .get_round()
1866                .unwrap_err()
1867            {
1868                InvalidRound(i) => i == 8,
1869                _ => false,
1870            }
1871        );
1872        assert!(
1873            match Evaluator::new(b"round(1,2", &mut Cache::new(), &mut None, &mut Vec::new())
1874                .get_round()
1875                .unwrap_err()
1876            {
1877                InvalidRound(i) => i == 9,
1878                _ => false,
1879            }
1880        );
1881        assert!(match Evaluator::new(
1882            b"round(1,10)",
1883            &mut Cache::new(),
1884            &mut None,
1885            &mut Vec::new()
1886        )
1887        .get_round()
1888        .unwrap_err()
1889        {
1890            InvalidRound(i) => i == 9,
1891            _ => false,
1892        });
1893        assert!(
1894            match Evaluator::new(b"round(1,a)", &mut Cache::new(), &mut None, &mut Vec::new())
1895                .get_round()
1896                .unwrap_err()
1897            {
1898                InvalidRound(i) => i == 8,
1899                _ => false,
1900            }
1901        );
1902        assert!(
1903            Evaluator::new(
1904                b"round(2, 7)",
1905                &mut Cache::new(),
1906                &mut None,
1907                &mut Vec::new()
1908            )
1909            .get_round()
1910            .unwrap()
1911                == Some(Ratio::from_integer(BigInt::from_biguint(
1912                    Sign::Plus,
1913                    BigUint::new(vec![2])
1914                )))
1915        );
1916        assert!(
1917            Evaluator::new(
1918                b"round(2.677, 1)",
1919                &mut Cache::new(),
1920                &mut None,
1921                &mut Vec::new()
1922            )
1923            .get_round()
1924            .unwrap()
1925                == Some(Ratio::new(
1926                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![27])),
1927                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![10]))
1928                ))
1929        );
1930    }
1931    #[cfg(feature = "rand")]
1932    #[test]
1933    fn rand() {
1934        assert!(match Evaluator::new(
1935            b"rand(1",
1936            &mut Cache::new(),
1937            &mut None,
1938            &mut Vec::new(),
1939            &mut rand::rng()
1940        )
1941        .get_rand()
1942        .unwrap_err()
1943        {
1944            LangErr::InvalidRand(i) => i == 6,
1945            _ => false,
1946        });
1947        assert!(match Evaluator::new(
1948            b"rand(1,2",
1949            &mut Cache::new(),
1950            &mut None,
1951            &mut Vec::new(),
1952            &mut rand::rng()
1953        )
1954        .get_rand()
1955        .unwrap_err()
1956        {
1957            LangErr::InvalidRand(i) => i == 8,
1958            _ => false,
1959        });
1960        assert!(match Evaluator::new(
1961            b"rand(1/2,3/4)",
1962            &mut Cache::new(),
1963            &mut None,
1964            &mut Vec::new(),
1965            &mut rand::rng(),
1966        )
1967        .get_rand()
1968        .unwrap_err()
1969        {
1970            LangErr::RandNoInts(i) => i == 13,
1971            _ => false,
1972        });
1973        assert!(match Evaluator::new(
1974            b"rand(-100000000000000000000000,-1000000000000000000000)",
1975            &mut Cache::new(),
1976            &mut None,
1977            &mut Vec::new(),
1978            &mut rand::rng(),
1979        )
1980        .get_rand()
1981        .unwrap_err()
1982        {
1983            LangErr::RandNoInts(i) => i == 55,
1984            _ => false,
1985        });
1986        assert!(match Evaluator::new(
1987            b"rand(2/3,1/3)",
1988            &mut Cache::new(),
1989            &mut None,
1990            &mut Vec::new(),
1991            &mut rand::rng(),
1992        )
1993        .get_rand()
1994        .unwrap_err()
1995        {
1996            LangErr::RandInvalidArgs(i) => i == 13,
1997            _ => false,
1998        });
1999        // If the input does not start with 'rand(', then it's invalid since get_rand must only be called as the last terminal expression which means whitespace must be consumed already.
2000        assert!(match Evaluator::new(
2001            b" rand(2/3,2)",
2002            &mut Cache::new(),
2003            &mut None,
2004            &mut Vec::new(),
2005            &mut rand::rng(),
2006        )
2007        .get_rand()
2008        .unwrap_err()
2009        {
2010            MissingTerm(i) => i == 0,
2011            _ => false,
2012        });
2013        assert!(
2014            Evaluator::new(
2015                b"rand(2, 7)",
2016                &mut Cache::new(),
2017                &mut None,
2018                &mut Vec::new(),
2019                &mut rand::rng()
2020            )
2021            .get_rand()
2022            .map(|r| {
2023                let int = r.numer();
2024                int >= &BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
2025                    && *int <= BigInt::from_biguint(Sign::Plus, BigUint::new(vec![7]))
2026            })
2027            .unwrap()
2028        );
2029        assert!(
2030            Evaluator::new(
2031                b"rand()",
2032                &mut Cache::new(),
2033                &mut None,
2034                &mut Vec::new(),
2035                &mut rand::rng()
2036            )
2037            .get_rand()
2038            .map(|r| {
2039                let int = r.numer();
2040                int >= &BigInt::from(i64::MIN) && *int <= BigInt::from(i64::MAX)
2041            })
2042            .unwrap()
2043        );
2044        for _ in 0..100 {
2045            assert!(
2046                Evaluator::new(
2047                    b"rand(2, 2)",
2048                    &mut Cache::new(),
2049                    &mut None,
2050                    &mut Vec::new(),
2051                    &mut rand::rng()
2052                )
2053                .get_rand()
2054                .map(|r| *r.numer() == BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
2055                .unwrap()
2056            );
2057        }
2058    }
2059    #[cfg(feature = "rand")]
2060    #[test]
2061    #[ignore]
2062    fn rand_uni() {
2063        // Test rand on an interval that is not a power of 2 in size.
2064        // This causes rand to adjust the interval to enforce uniformity.
2065        let mut vals = [0u32; 3];
2066        let mut vec = Vec::new();
2067        let mut cache = Cache::new();
2068        let mut none = None;
2069        const COUNT: u32 = 999999;
2070        for _ in 1..COUNT {
2071            vals[(Evaluator::new(
2072                b"rand(-1, 1)",
2073                &mut cache,
2074                &mut none,
2075                &mut vec,
2076                &mut rand::rng(),
2077            )
2078            .get_rand()
2079            .unwrap()
2080            .numer()
2081            .to_i32()
2082            .unwrap()
2083                + 1) as usize] += 1;
2084        }
2085        // Test that the distribution is within 1% of what is expected.
2086        assert!(
2087            vals.into_iter()
2088                .try_fold(false, |_, r| {
2089                    if r < COUNT * 33 / 100 || r > COUNT * 101 / 300 {
2090                        Err(false)
2091                    } else {
2092                        Ok(true)
2093                    }
2094                })
2095                .unwrap()
2096        );
2097    }
2098    #[test]
2099    fn term() {
2100        #[cfg(not(feature = "rand"))]
2101        assert!(
2102            Evaluator::new(b"0000.00000", &mut Cache::new(), &mut None, &mut Vec::new())
2103                .get_term()
2104                .unwrap()
2105                == Ratio::from_integer(BigInt::from_biguint(
2106                    Sign::NoSign,
2107                    BigUint::new(Vec::new())
2108                ))
2109        );
2110        #[cfg(not(feature = "rand"))]
2111        assert!(
2112            Evaluator::new(b"(4)", &mut Cache::new(), &mut None, &mut Vec::new())
2113                .get_term()
2114                .unwrap()
2115                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])))
2116        );
2117        #[cfg(not(feature = "rand"))]
2118        assert!(
2119            Evaluator::new(
2120                b"round(-2/3,2)",
2121                &mut Cache::new(),
2122                &mut None,
2123                &mut Vec::new()
2124            )
2125            .get_term()
2126            .unwrap()
2127                == Ratio::new(
2128                    BigInt::from_biguint(Sign::Minus, BigUint::new(vec![67])),
2129                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![100]))
2130                )
2131        );
2132        #[cfg(feature = "rand")]
2133        assert!(
2134            Evaluator::new(
2135                b"rand()",
2136                &mut Cache::new(),
2137                &mut None,
2138                &mut Vec::new(),
2139                &mut rand::rng()
2140            )
2141            .get_term()
2142            .is_ok()
2143        );
2144        #[cfg(feature = "rand")]
2145        assert!(
2146            Evaluator::new(
2147                b"rand(-13/93, 833)",
2148                &mut Cache::new(),
2149                &mut None,
2150                &mut Vec::new(),
2151                &mut rand::rng(),
2152            )
2153            .get_term()
2154            .is_ok()
2155        );
2156        #[cfg(not(feature = "rand"))]
2157        assert!(
2158            match Evaluator::new(b"rand()", &mut Cache::new(), &mut None, &mut Vec::new())
2159                .get_term()
2160                .unwrap_err()
2161            {
2162                MissingTerm(i) => i == 0,
2163                _ => false,
2164            }
2165        );
2166        #[cfg(not(feature = "rand"))]
2167        assert!(
2168            Evaluator::new(b"|4|", &mut Cache::new(), &mut None, &mut Vec::new())
2169                .get_term()
2170                .unwrap()
2171                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])))
2172        );
2173        // Terminal expressions do no clean up before or after.
2174        #[cfg(not(feature = "rand"))]
2175        assert!(
2176            match Evaluator::new(b" 2", &mut Cache::new(), &mut None, &mut Vec::new())
2177                .get_term()
2178                .unwrap_err()
2179            {
2180                MissingTerm(i) => i == 0,
2181                _ => false,
2182            }
2183        );
2184        #[cfg(not(feature = "rand"))]
2185        let mut prev = None;
2186        #[cfg(not(feature = "rand"))]
2187        let mut cache = Cache::new();
2188        #[cfg(not(feature = "rand"))]
2189        Evaluator::new(b"1\n", &mut cache, &mut prev, &mut Vec::new())
2190            .evaluate()
2191            .unwrap();
2192        #[cfg(not(feature = "rand"))]
2193        Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
2194            .evaluate()
2195            .unwrap();
2196        #[cfg(not(feature = "rand"))]
2197        assert!(
2198            Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new())
2199                .get_term()
2200                .unwrap()
2201                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2202        );
2203    }
2204    #[cfg(not(feature = "rand"))]
2205    #[test]
2206    fn factorial() {
2207        // Negative integer is not allowed.
2208        assert!(
2209            match Evaluator::new(b"(-1)!", &mut Cache::new(), &mut None, &mut Vec::new())
2210                .get_fact()
2211                .unwrap_err()
2212            {
2213                NotNonNegIntFact(i) => i == 5,
2214                _ => false,
2215            }
2216        );
2217        // Non-integer is not allowed.
2218        assert!(
2219            match Evaluator::new(b"2.5!", &mut Cache::new(), &mut None, &mut Vec::new())
2220                .get_fact()
2221                .unwrap_err()
2222            {
2223                NotNonNegIntFact(i) => i == 4,
2224                _ => false,
2225            }
2226        );
2227        // factorials always become terminal expressions eventually.
2228        assert!(
2229            Evaluator::new(b"7", &mut Cache::new(), &mut None, &mut Vec::new())
2230                .get_fact()
2231                .unwrap()
2232                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![7])))
2233        );
2234        assert!(
2235            Evaluator::new(b"(7)", &mut Cache::new(), &mut None, &mut Vec::new())
2236                .get_fact()
2237                .unwrap()
2238                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![7])))
2239        );
2240        assert!(
2241            Evaluator::new(b"|7|", &mut Cache::new(), &mut None, &mut Vec::new())
2242                .get_fact()
2243                .unwrap()
2244                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![7])))
2245        );
2246        let mut prev = None;
2247        let mut cache = Cache::new();
2248        Evaluator::new(b"3\n", &mut cache, &mut prev, &mut Vec::new())
2249            .evaluate()
2250            .unwrap();
2251        Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
2252            .evaluate()
2253            .unwrap();
2254        assert!(
2255            Evaluator::new(b"@!", &mut cache, &mut prev, &mut Vec::new())
2256                .get_fact()
2257                .unwrap()
2258                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![6])))
2259        );
2260        assert!(
2261            Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new())
2262                .get_fact()
2263                .unwrap()
2264                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3])))
2265        );
2266        // 0! = 1.
2267        assert!(
2268            Evaluator::new(b"0.0!", &mut Cache::new(), &mut None, &mut Vec::new())
2269                .get_fact()
2270                .unwrap()
2271                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2272        );
2273        // 1! = 1.
2274        assert!(
2275            Evaluator::new(b"1!", &mut Cache::new(), &mut None, &mut Vec::new())
2276                .get_fact()
2277                .unwrap()
2278                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2279        );
2280        // 4! = 24, and whitespace is not consumed.
2281        assert!(
2282            Evaluator::new(b"4! \t", &mut Cache::new(), &mut None, &mut Vec::new())
2283                .get_fact()
2284                .unwrap()
2285                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![24])))
2286        );
2287        // Factorials can be chained.
2288        assert!(
2289            Evaluator::new(b"3!! ", &mut Cache::new(), &mut None, &mut Vec::new())
2290                .get_fact()
2291                .unwrap()
2292                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![720])))
2293        );
2294        // only factorial is consumed.
2295        assert!(
2296            Evaluator::new(b"2!+3", &mut Cache::new(), &mut None, &mut Vec::new())
2297                .get_fact()
2298                .unwrap()
2299                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
2300        );
2301        // Error since leading/trailing whitespace is not consumed by factorial or higher precedence expressions.
2302        assert!(
2303            match Evaluator::new(b" 2!", &mut Cache::new(), &mut None, &mut Vec::new())
2304                .get_fact()
2305                .unwrap_err()
2306            {
2307                MissingTerm(i) => i == 0,
2308                _ => false,
2309            }
2310        );
2311        assert!(
2312            match Evaluator::new(b"\t2!", &mut Cache::new(), &mut None, &mut Vec::new())
2313                .get_fact()
2314                .unwrap_err()
2315            {
2316                MissingTerm(i) => i == 0,
2317                _ => false,
2318            }
2319        );
2320        // Error since negation is not consumed by factorial or higher precedence expressions.
2321        assert!(
2322            match Evaluator::new(b"-2!", &mut Cache::new(), &mut None, &mut Vec::new())
2323                .get_fact()
2324                .unwrap_err()
2325            {
2326                MissingTerm(i) => i == 0,
2327                _ => false,
2328            }
2329        );
2330    }
2331    #[cfg(not(feature = "rand"))]
2332    #[test]
2333    fn exp() {
2334        // 1 can be raised to anything and return 1.
2335        // Also white space is ignored between operator.
2336        assert!(
2337            Evaluator::new(b"1  ^\t  0", &mut Cache::new(), &mut None, &mut Vec::new())
2338                .get_exps()
2339                .unwrap()
2340                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2341        );
2342        assert!(
2343            Evaluator::new(b"1^0.5", &mut Cache::new(), &mut None, &mut Vec::new())
2344                .get_exps()
2345                .unwrap()
2346                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2347        );
2348        assert!(
2349            Evaluator::new(b"1^(-1/2)", &mut Cache::new(), &mut None, &mut Vec::new())
2350                .get_exps()
2351                .unwrap()
2352                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2353        );
2354        assert!(
2355            Evaluator::new(b"1.0^(-2)", &mut Cache::new(), &mut None, &mut Vec::new())
2356                .get_exps()
2357                .unwrap()
2358                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2359        );
2360        // 0 can be raised to any non-negative value and will always return 0 unless raised to 0 which will return 1.
2361        assert!(
2362            Evaluator::new(b"0^0", &mut Cache::new(), &mut None, &mut Vec::new())
2363                .get_exps()
2364                .unwrap()
2365                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2366        );
2367        assert!(
2368            Evaluator::new(b"0^1", &mut Cache::new(), &mut None, &mut Vec::new())
2369                .get_exps()
2370                .unwrap()
2371                == Ratio::from_integer(BigInt::from_biguint(Sign::NoSign, BigUint::new(vec![0])))
2372        );
2373        assert!(
2374            Evaluator::new(b"0^0.5", &mut Cache::new(), &mut None, &mut Vec::new())
2375                .get_exps()
2376                .unwrap()
2377                == Ratio::from_integer(BigInt::from_biguint(Sign::NoSign, BigUint::new(vec![0])))
2378        );
2379        // Anything else can only be raised to integers.
2380        assert!(
2381            Evaluator::new(b"4^0", &mut Cache::new(), &mut None, &mut Vec::new())
2382                .get_exps()
2383                .unwrap()
2384                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2385        );
2386        assert!(
2387            Evaluator::new(b"4^1", &mut Cache::new(), &mut None, &mut Vec::new())
2388                .get_exps()
2389                .unwrap()
2390                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])))
2391        );
2392        assert!(
2393            Evaluator::new(b"4^(-2)", &mut Cache::new(), &mut None, &mut Vec::new())
2394                .get_exps()
2395                .unwrap()
2396                == Ratio::new(
2397                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])),
2398                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![16]))
2399                )
2400        );
2401        assert!(
2402            Evaluator::new(b"(-4)^0", &mut Cache::new(), &mut None, &mut Vec::new())
2403                .get_exps()
2404                .unwrap()
2405                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2406        );
2407        assert!(
2408            Evaluator::new(b"(-4)^1", &mut Cache::new(), &mut None, &mut Vec::new())
2409                .get_exps()
2410                .unwrap()
2411                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![4])))
2412        );
2413        assert!(
2414            Evaluator::new(b"(-4)^2", &mut Cache::new(), &mut None, &mut Vec::new())
2415                .get_exps()
2416                .unwrap()
2417                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![16])))
2418        );
2419        assert!(
2420            Evaluator::new(b"(-4)^(-2)", &mut Cache::new(), &mut None, &mut Vec::new())
2421                .get_exps()
2422                .unwrap()
2423                == Ratio::new(
2424                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])),
2425                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![16]))
2426                )
2427        );
2428        assert!(
2429            Evaluator::new(b"(-4)^(-3)", &mut Cache::new(), &mut None, &mut Vec::new())
2430                .get_exps()
2431                .unwrap()
2432                == Ratio::new(
2433                    BigInt::from_biguint(Sign::Minus, BigUint::new(vec![1])),
2434                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64]))
2435                )
2436        );
2437        assert!(
2438            Evaluator::new(b"(2/3)^0", &mut Cache::new(), &mut None, &mut Vec::new())
2439                .get_exps()
2440                .unwrap()
2441                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2442        );
2443        assert!(
2444            Evaluator::new(b"(2/3)^(2)", &mut Cache::new(), &mut None, &mut Vec::new())
2445                .get_exps()
2446                .unwrap()
2447                == Ratio::new(
2448                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])),
2449                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![9]))
2450                )
2451        );
2452        assert!(
2453            Evaluator::new(b"(2/3)^(-3)", &mut Cache::new(), &mut None, &mut Vec::new())
2454                .get_exps()
2455                .unwrap()
2456                == Ratio::new(
2457                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![27])),
2458                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8]))
2459                )
2460        );
2461        assert!(
2462            Evaluator::new(b"(-2/3)^0", &mut Cache::new(), &mut None, &mut Vec::new())
2463                .get_exps()
2464                .unwrap()
2465                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2466        );
2467        assert!(
2468            Evaluator::new(b"(-2/3)^(2)", &mut Cache::new(), &mut None, &mut Vec::new())
2469                .get_exps()
2470                .unwrap()
2471                == Ratio::new(
2472                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])),
2473                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![9]))
2474                )
2475        );
2476        assert!(
2477            Evaluator::new(b"(-2/3)^(3)", &mut Cache::new(), &mut None, &mut Vec::new())
2478                .get_exps()
2479                .unwrap()
2480                == Ratio::new(
2481                    BigInt::from_biguint(Sign::Minus, BigUint::new(vec![8])),
2482                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![27]))
2483                )
2484        );
2485        assert!(
2486            Evaluator::new(
2487                b"(-2/3)^(-2)",
2488                &mut Cache::new(),
2489                &mut None,
2490                &mut Vec::new()
2491            )
2492            .get_exps()
2493            .unwrap()
2494                == Ratio::new(
2495                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![9])),
2496                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4]))
2497                )
2498        );
2499        assert!(
2500            Evaluator::new(
2501                b"(-2/3)^(-3)",
2502                &mut Cache::new(),
2503                &mut None,
2504                &mut Vec::new()
2505            )
2506            .get_exps()
2507            .unwrap()
2508                == Ratio::new(
2509                    BigInt::from_biguint(Sign::Minus, BigUint::new(vec![27])),
2510                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8]))
2511                )
2512        );
2513        assert!(
2514            Evaluator::new(
2515                b"(4/9)^(-1/2)",
2516                &mut Cache::new(),
2517                &mut None,
2518                &mut Vec::new()
2519            )
2520            .get_exps()
2521            .unwrap()
2522                == Ratio::new(
2523                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3])),
2524                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
2525                )
2526        );
2527        // Error since 0 cannot be raised to a negative power.
2528        assert!(
2529            match Evaluator::new(b"0^(-1)", &mut Cache::new(), &mut None, &mut Vec::new())
2530                .get_exps()
2531                .unwrap_err()
2532            {
2533                ExpDivByZero(i) => i == 6,
2534                _ => false,
2535            }
2536        );
2537        // Error since anything other than 0 or 1 cannot be raised to a non-integer power or (+/-) 1/2.
2538        assert!(
2539            match Evaluator::new(b"2^(1/3)", &mut Cache::new(), &mut None, &mut Vec::new())
2540                .get_exps()
2541                .unwrap_err()
2542            {
2543                ExpIsNotIntOrOneHalf(i) => i == 7,
2544                _ => false,
2545            }
2546        );
2547        // When exponent is (+/-) 1/2, base has to be the square of a rational number.
2548        assert!(
2549            match Evaluator::new(b"2^(1/2)", &mut Cache::new(), &mut None, &mut Vec::new())
2550                .get_exps()
2551                .unwrap_err()
2552            {
2553                SqrtDoesNotExist(i) => i == 7,
2554                _ => false,
2555            }
2556        );
2557        // exps always become factorials eventually.
2558        assert!(
2559            Evaluator::new(b"3!", &mut Cache::new(), &mut None, &mut Vec::new())
2560                .get_exps()
2561                .unwrap()
2562                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![6])))
2563        );
2564        // exponentiation has lower precedence than factorials.
2565        assert!(
2566            Evaluator::new(b"2^3!", &mut Cache::new(), &mut None, &mut Vec::new())
2567                .get_exps()
2568                .unwrap()
2569                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64])))
2570        );
2571        assert!(
2572            Evaluator::new(b"3!^2", &mut Cache::new(), &mut None, &mut Vec::new())
2573                .get_exps()
2574                .unwrap()
2575                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![36])))
2576        );
2577        // Error since leading/trailing whitespace is not consumed by exponentiation or higher precedence expressions.
2578        assert!(
2579            match Evaluator::new(b" 2^2", &mut Cache::new(), &mut None, &mut Vec::new())
2580                .get_exps()
2581                .unwrap_err()
2582            {
2583                MissingTerm(i) => i == 0,
2584                _ => false,
2585            }
2586        );
2587        assert!(
2588            match Evaluator::new(b"\t2^2", &mut Cache::new(), &mut None, &mut Vec::new())
2589                .get_exps()
2590                .unwrap_err()
2591            {
2592                MissingTerm(i) => i == 0,
2593                _ => false,
2594            }
2595        );
2596    }
2597    #[cfg(not(feature = "rand"))]
2598    #[test]
2599    fn neg() {
2600        assert!(
2601            Evaluator::new(b"-1", &mut Cache::new(), &mut None, &mut Vec::new())
2602                .get_neg()
2603                .unwrap()
2604                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![1])))
2605        );
2606        assert!(
2607            Evaluator::new(b"- \t  -  1", &mut Cache::new(), &mut None, &mut Vec::new())
2608                .get_neg()
2609                .unwrap()
2610                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2611        );
2612        assert!(
2613            Evaluator::new(b"-0", &mut Cache::new(), &mut None, &mut Vec::new())
2614                .get_neg()
2615                .unwrap()
2616                == Ratio::from_integer(BigInt::from_biguint(
2617                    Sign::NoSign,
2618                    BigUint::new(Vec::new())
2619                ))
2620        );
2621        // negation has lower precedence than exponentiation.
2622        assert!(
2623            Evaluator::new(b"-2^2", &mut Cache::new(), &mut None, &mut Vec::new())
2624                .get_neg()
2625                .unwrap()
2626                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![4])))
2627        );
2628        // negation always becomes exponentiation eventually.
2629        assert!(
2630            Evaluator::new(b"2.0^2.0", &mut Cache::new(), &mut None, &mut Vec::new())
2631                .get_neg()
2632                .unwrap()
2633                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])))
2634        );
2635        // Error since leading/trailing whitespace is not consumed by exponentiation or higher precedence expressions.
2636        assert!(
2637            match Evaluator::new(b" -2", &mut Cache::new(), &mut None, &mut Vec::new())
2638                .get_neg()
2639                .unwrap_err()
2640            {
2641                MissingTerm(i) => i == 0,
2642                _ => false,
2643            }
2644        );
2645        assert!(
2646            match Evaluator::new(b"\t-2", &mut Cache::new(), &mut None, &mut Vec::new())
2647                .get_neg()
2648                .unwrap_err()
2649            {
2650                MissingTerm(i) => i == 0,
2651                _ => false,
2652            }
2653        );
2654    }
2655    #[cfg(not(feature = "rand"))]
2656    #[test]
2657    fn mult() {
2658        assert!(
2659            Evaluator::new(b"2  *   3", &mut Cache::new(), &mut None, &mut Vec::new())
2660                .get_mults()
2661                .unwrap()
2662                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![6])))
2663        );
2664        assert!(
2665            Evaluator::new(
2666                b"-2  * \t  3",
2667                &mut Cache::new(),
2668                &mut None,
2669                &mut Vec::new()
2670            )
2671            .get_mults()
2672            .unwrap()
2673                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![6])))
2674        );
2675        assert!(
2676            Evaluator::new(
2677                b"2\t  *   -3.0",
2678                &mut Cache::new(),
2679                &mut None,
2680                &mut Vec::new()
2681            )
2682            .get_mults()
2683            .unwrap()
2684                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![6])))
2685        );
2686        assert!(
2687            Evaluator::new(b"-2.5*-3.5", &mut Cache::new(), &mut None, &mut Vec::new())
2688                .get_mults()
2689                .unwrap()
2690                == Ratio::new(
2691                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![35])),
2692                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4]))
2693                )
2694        );
2695        assert!(
2696            Evaluator::new(b"4.0\t /  6", &mut Cache::new(), &mut None, &mut Vec::new())
2697                .get_mults()
2698                .unwrap()
2699                == Ratio::new(
2700                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])),
2701                    BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3]))
2702                )
2703        );
2704        assert!(
2705            Evaluator::new(b"6/3", &mut Cache::new(), &mut None, &mut Vec::new())
2706                .get_mults()
2707                .unwrap()
2708                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
2709        );
2710        assert!(
2711            Evaluator::new(b"-6/3", &mut Cache::new(), &mut None, &mut Vec::new())
2712                .get_mults()
2713                .unwrap()
2714                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![2])))
2715        );
2716        assert!(
2717            Evaluator::new(b"6/-3", &mut Cache::new(), &mut None, &mut Vec::new())
2718                .get_mults()
2719                .unwrap()
2720                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![2])))
2721        );
2722        assert!(
2723            Evaluator::new(
2724                b"-  6 /\t -  3",
2725                &mut Cache::new(),
2726                &mut None,
2727                &mut Vec::new()
2728            )
2729            .get_mults()
2730            .unwrap()
2731                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
2732        );
2733        // Number literals are not strictly equivalent to "ratios" as "ratios" don't exist (i.e., 2/3 is not the ratio of 2 to 3 but is the rational number two divided by the rational number 3).
2734        assert!(
2735            Evaluator::new(b"1/1.5", &mut Cache::new(), &mut None, &mut Vec::new())
2736                .get_mults()
2737                .unwrap()
2738                != Evaluator::new(b"1/3/2", &mut Cache::new(), &mut None, &mut Vec::new())
2739                    .get_mults()
2740                    .unwrap()
2741        );
2742        assert!(
2743            Evaluator::new(b"1/1.5", &mut Cache::new(), &mut None, &mut Vec::new())
2744                .get_mults()
2745                .unwrap()
2746                == Evaluator::new(b"1/(3/2)", &mut Cache::new(), &mut None, &mut Vec::new())
2747                    .get_mults()
2748                    .unwrap()
2749        );
2750        // multiplication always becomes negation eventually.
2751        assert!(
2752            Evaluator::new(b"-2.0", &mut Cache::new(), &mut None, &mut Vec::new())
2753                .get_mults()
2754                .unwrap()
2755                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![2])))
2756        );
2757        // Error since leading/trailing whitespace is not consumed by multiplication or higher precedence expressions.
2758        assert!(
2759            match Evaluator::new(b" 2*2", &mut Cache::new(), &mut None, &mut Vec::new())
2760                .get_mults()
2761                .unwrap_err()
2762            {
2763                MissingTerm(i) => i == 0,
2764                _ => false,
2765            }
2766        );
2767        assert!(
2768            match Evaluator::new(b"\t2/2", &mut Cache::new(), &mut None, &mut Vec::new())
2769                .get_mults()
2770                .unwrap_err()
2771            {
2772                MissingTerm(i) => i == 0,
2773                _ => false,
2774            }
2775        );
2776        assert!(
2777            Evaluator::new(
2778                b"4.0\t mod  6",
2779                &mut Cache::new(),
2780                &mut None,
2781                &mut Vec::new()
2782            )
2783            .get_mults()
2784            .unwrap()
2785                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])),)
2786        );
2787        assert!(
2788            Evaluator::new(b"5 mod 3", &mut Cache::new(), &mut None, &mut Vec::new())
2789                .get_mults()
2790                .unwrap()
2791                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
2792        );
2793        assert!(
2794            Evaluator::new(b"-5 mod 3", &mut Cache::new(), &mut None, &mut Vec::new())
2795                .get_mults()
2796                .unwrap()
2797                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2798        );
2799        assert!(
2800            Evaluator::new(b"5 mod -3", &mut Cache::new(), &mut None, &mut Vec::new())
2801                .get_mults()
2802                .unwrap()
2803                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
2804        );
2805        assert!(
2806            Evaluator::new(
2807                b"-5   mod\t -3",
2808                &mut Cache::new(),
2809                &mut None,
2810                &mut Vec::new()
2811            )
2812            .get_mults()
2813            .unwrap()
2814                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2815        );
2816        // Cannot divide by 0.
2817        assert!(
2818            match Evaluator::new(b"2/0", &mut Cache::new(), &mut None, &mut Vec::new())
2819                .get_mults()
2820                .unwrap_err()
2821            {
2822                DivByZero(i) => i == 3,
2823                _ => false,
2824            }
2825        );
2826        assert!(
2827            match Evaluator::new(b"2 mod 0", &mut Cache::new(), &mut None, &mut Vec::new())
2828                .get_mults()
2829                .unwrap_err()
2830            {
2831                ModZero(i) => i == 7,
2832                _ => false,
2833            }
2834        );
2835        // Right and left operands of mod must be integers.
2836        assert!(
2837            match Evaluator::new(b"3.2 mod 1", &mut Cache::new(), &mut None, &mut Vec::new())
2838                .get_mults()
2839                .unwrap_err()
2840            {
2841                ModIsNotInt(i) => i == 4,
2842                _ => false,
2843            }
2844        );
2845        assert!(
2846            match Evaluator::new(b"3 mod 3.2", &mut Cache::new(), &mut None, &mut Vec::new())
2847                .get_mults()
2848                .unwrap_err()
2849            {
2850                ModIsNotInt(i) => i == 9,
2851                _ => false,
2852            }
2853        );
2854        // multiplication has lower precedence than exponentiation.
2855        assert!(
2856            Evaluator::new(b"2*2^2", &mut Cache::new(), &mut None, &mut Vec::new())
2857                .get_mults()
2858                .unwrap()
2859                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8])))
2860        );
2861        assert!(
2862            Evaluator::new(b"8/2^2", &mut Cache::new(), &mut None, &mut Vec::new())
2863                .get_mults()
2864                .unwrap()
2865                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
2866        );
2867        assert!(
2868            Evaluator::new(b"8 mod 3^2", &mut Cache::new(), &mut None, &mut Vec::new())
2869                .get_mults()
2870                .unwrap()
2871                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8])))
2872        );
2873    }
2874    #[cfg(not(feature = "rand"))]
2875    #[test]
2876    fn add() {
2877        assert!(
2878            Evaluator::new(b"2  +   3", &mut Cache::new(), &mut None, &mut Vec::new())
2879                .get_adds()
2880                .unwrap()
2881                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![5])))
2882        );
2883        assert!(
2884            Evaluator::new(b"-2  +   3", &mut Cache::new(), &mut None, &mut Vec::new())
2885                .get_adds()
2886                .unwrap()
2887                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2888        );
2889        assert!(
2890            Evaluator::new(
2891                b"2  +  \t -3.0",
2892                &mut Cache::new(),
2893                &mut None,
2894                &mut Vec::new()
2895            )
2896            .get_adds()
2897            .unwrap()
2898                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![1])))
2899        );
2900        assert!(
2901            Evaluator::new(b"-2.5+-3.5", &mut Cache::new(), &mut None, &mut Vec::new())
2902                .get_adds()
2903                .unwrap()
2904                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![6])))
2905        );
2906        assert!(
2907            Evaluator::new(b"4.0\t -  6", &mut Cache::new(), &mut None, &mut Vec::new())
2908                .get_adds()
2909                .unwrap()
2910                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![2])))
2911        );
2912        assert!(
2913            Evaluator::new(b"6-3", &mut Cache::new(), &mut None, &mut Vec::new())
2914                .get_adds()
2915                .unwrap()
2916                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3])))
2917        );
2918        assert!(
2919            Evaluator::new(b"-6-3", &mut Cache::new(), &mut None, &mut Vec::new())
2920                .get_adds()
2921                .unwrap()
2922                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![9])))
2923        );
2924        assert!(
2925            Evaluator::new(b"6--3", &mut Cache::new(), &mut None, &mut Vec::new())
2926                .get_adds()
2927                .unwrap()
2928                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![9])))
2929        );
2930        assert!(
2931            Evaluator::new(
2932                b"-  6 -\t -  3",
2933                &mut Cache::new(),
2934                &mut None,
2935                &mut Vec::new()
2936            )
2937            .get_adds()
2938            .unwrap()
2939                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![3])))
2940        );
2941        // addition always becomes multiplication eventually.
2942        assert!(
2943            Evaluator::new(b"2 * 8", &mut Cache::new(), &mut None, &mut Vec::new())
2944                .get_adds()
2945                .unwrap()
2946                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![16])))
2947        );
2948        assert!(
2949            Evaluator::new(b"8 /\t 2", &mut Cache::new(), &mut None, &mut Vec::new())
2950                .get_adds()
2951                .unwrap()
2952                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])))
2953        );
2954        // Error since leading/trailing whitespace is not consumed by addition or higher precedence expressions.
2955        assert!(
2956            match Evaluator::new(b" 2+2", &mut Cache::new(), &mut None, &mut Vec::new())
2957                .get_adds()
2958                .unwrap_err()
2959            {
2960                MissingTerm(i) => i == 0,
2961                _ => false,
2962            }
2963        );
2964        assert!(
2965            match Evaluator::new(b" 2-2", &mut Cache::new(), &mut None, &mut Vec::new())
2966                .get_adds()
2967                .unwrap_err()
2968            {
2969                MissingTerm(i) => i == 0,
2970                _ => false,
2971            }
2972        );
2973        // addition has lower precedence than multiplication.
2974        assert!(
2975            Evaluator::new(b"2+2*2", &mut Cache::new(), &mut None, &mut Vec::new())
2976                .get_adds()
2977                .unwrap()
2978                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![6])))
2979        );
2980        assert!(
2981            Evaluator::new(b"2+2/2", &mut Cache::new(), &mut None, &mut Vec::new())
2982                .get_adds()
2983                .unwrap()
2984                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3])))
2985        );
2986        assert!(
2987            Evaluator::new(b"2-2*2", &mut Cache::new(), &mut None, &mut Vec::new())
2988                .get_adds()
2989                .unwrap()
2990                == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![2])))
2991        );
2992        assert!(
2993            Evaluator::new(b"2-2/2", &mut Cache::new(), &mut None, &mut Vec::new())
2994                .get_adds()
2995                .unwrap()
2996                == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
2997        );
2998    }
2999    #[cfg(not(feature = "rand"))]
3000    #[test]
3001    fn exit() {
3002        assert!(
3003            match Evaluator::new(b"  q    \n", &mut Cache::new(), &mut None, &mut Vec::new())
3004                .evaluate()
3005                .unwrap()
3006            {
3007                O::Exit => true,
3008                _ => false,
3009            }
3010        );
3011        assert!(match Evaluator::new(
3012            b"  q    \r\n",
3013            &mut Cache::new(),
3014            &mut None,
3015            &mut Vec::new()
3016        )
3017        .evaluate()
3018        .unwrap()
3019        {
3020            O::Exit => true,
3021            _ => false,
3022        });
3023        assert!(
3024            match Evaluator::new(b"q\n", &mut Cache::new(), &mut None, &mut Vec::new())
3025                .evaluate()
3026                .unwrap()
3027            {
3028                O::Exit => true,
3029                _ => false,
3030            }
3031        );
3032        assert!(
3033            match Evaluator::new(b"q\r\n", &mut Cache::new(), &mut None, &mut Vec::new())
3034                .evaluate()
3035                .unwrap()
3036            {
3037                O::Exit => true,
3038                _ => false,
3039            }
3040        );
3041        assert!(
3042            match Evaluator::new(b"\rq\n", &mut Cache::new(), &mut None, &mut Vec::new())
3043                .evaluate()
3044                .unwrap_err()
3045            {
3046                MissingTerm(i) => i == 0,
3047                _ => false,
3048            }
3049        );
3050        assert!(
3051            match Evaluator::new(b"\tq\n", &mut Cache::new(), &mut None, &mut Vec::new())
3052                .evaluate()
3053                .unwrap()
3054            {
3055                O::Exit => true,
3056                _ => false,
3057            }
3058        );
3059        assert!(
3060            match Evaluator::new(b"q\n\n", &mut Cache::new(), &mut None, &mut Vec::new())
3061                .evaluate()
3062                .unwrap_err()
3063            {
3064                InvalidQuit => true,
3065                _ => false,
3066            }
3067        );
3068        assert!(
3069            match Evaluator::new(b"\nq\n", &mut Cache::new(), &mut None, &mut Vec::new())
3070                .evaluate()
3071                .unwrap_err()
3072            {
3073                MissingTerm(i) => i == 0,
3074                _ => false,
3075            }
3076        );
3077        assert!(
3078            match Evaluator::new(b"q", &mut Cache::new(), &mut None, &mut Vec::new())
3079                .evaluate()
3080                .unwrap()
3081            {
3082                O::Exit => true,
3083                _ => false,
3084            }
3085        );
3086    }
3087    #[cfg(not(feature = "rand"))]
3088    #[test]
3089    fn store() {
3090        let mut prev = None;
3091        let mut cache = Cache::new();
3092        Evaluator::new(b"1\n", &mut cache, &mut prev, &mut Vec::new())
3093            .evaluate()
3094            .unwrap();
3095        assert!(cache.is_empty());
3096        assert!(
3097            match Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
3098                .evaluate()
3099                .unwrap()
3100            {
3101                O::Store(o) =>
3102                    o.as_ref().unwrap()
3103                        == &Ratio::from_integer(BigInt::from_biguint(
3104                            Sign::Plus,
3105                            BigUint::new(vec![1])
3106                        )),
3107                _ => false,
3108            }
3109        );
3110        assert!(cache.len() == 1);
3111    }
3112    #[cfg(not(feature = "rand"))]
3113    #[test]
3114    fn eval() {
3115        use core::str::FromStr;
3116        let mut prev = None;
3117        let mut cache = Cache::new();
3118        let mut exp = Vec::new();
3119        assert!(
3120            match Evaluator::new(b"1+2\n", &mut cache, &mut prev, &mut exp)
3121                .evaluate()
3122                .unwrap()
3123            {
3124                O::Eval(i) =>
3125                    i == &Ratio::from_integer(BigInt::from_biguint(
3126                        Sign::Plus,
3127                        BigUint::new(vec![3])
3128                    )),
3129                _ => false,
3130            }
3131        );
3132        assert!(
3133            match Evaluator::new(b"\t  s  \n", &mut cache, &mut prev, &mut exp)
3134                .evaluate()
3135                .unwrap()
3136            {
3137                O::Store(o) =>
3138                    o.as_ref().unwrap()
3139                        == &Ratio::from_integer(BigInt::from_biguint(
3140                            Sign::Plus,
3141                            BigUint::new(vec![3])
3142                        )),
3143                _ => false,
3144            }
3145        );
3146        assert!(
3147            match Evaluator::new(b"-1/2+2*@\n", &mut cache, &mut prev, &mut exp)
3148                .evaluate()
3149                .unwrap()
3150            {
3151                O::Eval(i) =>
3152                    i == &Ratio::new(
3153                        BigInt::from_biguint(Sign::Plus, BigUint::new(vec![11])),
3154                        BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
3155                    ),
3156                _ => false,
3157            }
3158        );
3159        assert!(
3160            match Evaluator::new(b"s\n", &mut cache, &mut prev, &mut exp)
3161                .evaluate()
3162                .unwrap()
3163            {
3164                O::Store(o) =>
3165                    o == &Some(Ratio::new(
3166                        BigInt::from_biguint(Sign::Plus, BigUint::new(vec![11])),
3167                        BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
3168                    )),
3169                _ => false,
3170            }
3171        );
3172        assert!(
3173            match Evaluator::new(b"@^@2!\r\n", &mut cache, &mut prev, &mut exp)
3174                .evaluate()
3175                .unwrap()
3176            {
3177                O::Eval(i) =>
3178                    i == &Ratio::new(
3179                        BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1771561])),
3180                        BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64]))
3181                    ),
3182                _ => false,
3183            }
3184        );
3185        assert!(
3186            match Evaluator::new(b"s\n", &mut cache, &mut prev, &mut exp)
3187                .evaluate()
3188                .unwrap()
3189            {
3190                O::Store(o) =>
3191                    o == &Some(Ratio::new(
3192                        BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1771561])),
3193                        BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64]))
3194                    )),
3195                _ => false,
3196            }
3197        );
3198        // Verified with Wolfram Alpha.
3199        assert!(match Evaluator::new(b" \t 1 + (2 * |(7.98\t - 12/7)|) / 4!^@3!^|1-3|\t  \n", &mut cache, &mut prev, &mut exp).evaluate().unwrap() {
3200            O::Eval(i) => i == &Ratio::from_str("2841328814244153299237884950647090899374680152474331/2841328814244153299237884950647090899374680152473600").unwrap(),
3201            _ => false,
3202        });
3203        assert!(match Evaluator::new(
3204            b" \t round(19/6,0)!\t  \r\n",
3205            &mut cache,
3206            &mut prev,
3207            &mut exp
3208        )
3209        .evaluate()
3210        .unwrap()
3211        {
3212            O::Eval(i) =>
3213                i == &Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![6]))),
3214            _ => false,
3215        });
3216        assert!(match Evaluator::new(
3217            b" \t 2^round(19/6,0)!\t  \r\n",
3218            &mut cache,
3219            &mut prev,
3220            &mut exp
3221        )
3222        .evaluate()
3223        .unwrap()
3224        {
3225            O::Eval(i) =>
3226                i == &Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64]))),
3227            _ => false,
3228        });
3229        assert!(
3230            match Evaluator::new(b"round(19/6,0)^2\t\n", &mut cache, &mut prev, &mut exp)
3231                .evaluate()
3232                .unwrap()
3233            {
3234                O::Eval(i) =>
3235                    i == &Ratio::from_integer(BigInt::from_biguint(
3236                        Sign::Plus,
3237                        BigUint::new(vec![9])
3238                    )),
3239                _ => false,
3240            }
3241        );
3242        // Invalid UTF-8 does not cause a panic!.
3243        assert!(
3244            match Evaluator::new(&[255, 255, 255, b'\n'], &mut cache, &mut prev, &mut exp)
3245                .evaluate()
3246                .unwrap_err()
3247            {
3248                MissingTerm(i) => i == 0,
3249                _ => false,
3250            }
3251        );
3252        assert!(
3253            match Evaluator::new(&[b'2', 255, b'\n'], &mut cache, &mut prev, &mut exp)
3254                .evaluate()
3255                .unwrap_err()
3256            {
3257                TrailingSyms(i) => i == 1,
3258                _ => false,
3259            }
3260        );
3261        // Exactly one newline is required.
3262        assert!(
3263            match Evaluator::new(b"2\n\n", &mut cache, &mut prev, &mut exp)
3264                .evaluate()
3265                .unwrap_err()
3266            {
3267                TrailingSyms(i) => i == 1,
3268                _ => false,
3269            }
3270        );
3271        assert!(
3272            prev == Some(Ratio::from_integer(BigInt::from_biguint(
3273                Sign::Plus,
3274                BigUint::new(vec![9])
3275            )))
3276        );
3277        assert!(match Evaluator::new(b"\n", &mut cache, &mut prev, &mut exp)
3278            .evaluate()
3279            .unwrap()
3280        {
3281            O::Empty(o) =>
3282                o == &Some(Ratio::from_integer(BigInt::from_biguint(
3283                    Sign::Plus,
3284                    BigUint::new(vec![9])
3285                ))),
3286            _ => false,
3287        });
3288        assert!(
3289            prev == Some(Ratio::from_integer(BigInt::from_biguint(
3290                Sign::Plus,
3291                BigUint::new(vec![9])
3292            )))
3293        );
3294        assert!(
3295            match Evaluator::new(b"\r\n", &mut cache, &mut prev.clone(), &mut exp)
3296                .evaluate()
3297                .unwrap()
3298            {
3299                O::Empty(o) => *o == prev,
3300                _ => false,
3301            }
3302        );
3303        assert!(
3304            match Evaluator::new(&[0u8; 0], &mut cache, &mut prev.clone(), &mut exp)
3305                .evaluate()
3306                .unwrap()
3307            {
3308                O::Empty(o) => *o == prev,
3309                _ => false,
3310            }
3311        );
3312    }
3313    #[cfg(feature = "rand")]
3314    #[test]
3315    fn eval_iter() {
3316        use super::*;
3317        use num_traits::ToPrimitive;
3318        use std::io::{self, BufRead, Error, ErrorKind, Read};
3319        struct Reader<'a> {
3320            data: &'a [u8],
3321            err: bool,
3322        }
3323        impl<'a> Reader<'a> {
3324            fn new(data: &'a [u8]) -> Self {
3325                Self { data, err: true }
3326            }
3327        }
3328        impl<'a> Read for Reader<'a> {
3329            fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
3330                if self.err {
3331                    self.err = false;
3332                    Err(Error::new(ErrorKind::Other, ""))
3333                } else {
3334                    let len = usize::min(buf.len(), self.data.len());
3335                    buf[..len].copy_from_slice(&self.data[..len]);
3336                    Ok(len)
3337                }
3338            }
3339        }
3340        impl<'a> BufRead for Reader<'a> {
3341            fn fill_buf(&mut self) -> io::Result<&[u8]> {
3342                if self.err {
3343                    self.err = false;
3344                    Err(Error::new(ErrorKind::Other, ""))
3345                } else {
3346                    Ok(self.data)
3347                }
3348            }
3349            fn consume(&mut self, amt: usize) {
3350                self.data = &self.data[amt..];
3351            }
3352        }
3353        let mut iter = EvalIter::new(Reader::new(
3354            b"1+2\n4\n\nq\n5\ns\nrand() + rand(-139/@, 2984/134)\nab",
3355        ));
3356        assert!(match iter.lend_next().unwrap().unwrap_err() {
3357            E::Error(_) => true,
3358            _ => false,
3359        });
3360        assert!(match iter.lend_next().unwrap().unwrap() {
3361            O::Eval(r) => r.numer().to_i32().unwrap() == 3,
3362            _ => false,
3363        });
3364        assert!(match iter.lend_next().unwrap().unwrap() {
3365            O::Eval(r) => r.numer().to_i32().unwrap() == 4,
3366            _ => false,
3367        });
3368        assert!(match iter.lend_next().unwrap().unwrap() {
3369            O::Empty(r) => r.as_ref().unwrap().numer().to_i32().unwrap() == 4,
3370            _ => false,
3371        });
3372        assert!(iter.lend_next().is_none());
3373        assert!(match iter.lend_next().unwrap().unwrap() {
3374            O::Eval(r) => r.numer().to_i32().unwrap() == 5,
3375            _ => false,
3376        });
3377        assert!(match iter.lend_next().unwrap().unwrap() {
3378            O::Store(r) => r.as_ref().unwrap().numer().to_i32().unwrap() == 5,
3379            _ => false,
3380        });
3381        assert!(match iter.lend_next().unwrap().unwrap() {
3382            O::Eval(r) => r.is_integer(),
3383            _ => false,
3384        });
3385        assert!(match iter.lend_next().unwrap().unwrap_err() {
3386            E::LangErr(e) => match e {
3387                LangErr::MissingTerm(_) => true,
3388                _ => false,
3389            },
3390            _ => false,
3391        });
3392        assert!(iter.lend_next().is_none());
3393        assert!(iter.lend_next().is_none());
3394        assert!(iter.lend_next().is_none());
3395    }
3396}