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