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