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