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