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