calc_rational

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

lib.rs (129551B)


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