calc_rational

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

lib.rs (130453B)


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