calc_rational

CLI calculator for rational numbers.
git clone https://git.philomathiclife.com/repos/calc_rational
Log | Files | Refs | README

lib.rs (130046B)


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