diff --git a/examples/builder.rs b/examples/builder.rs index a43663cb..29a3658a 100644 --- a/examples/builder.rs +++ b/examples/builder.rs @@ -1,8 +1,4 @@ -use symbolica::{ - atom::{Atom, FunctionBuilder}, - fun, - state::State, -}; +use symbolica::{atom::Atom, fun, state::State}; fn main() { let x = Atom::parse("x").unwrap(); diff --git a/examples/collect.rs b/examples/collect.rs index 245603fb..99efd6d6 100644 --- a/examples/collect.rs +++ b/examples/collect.rs @@ -1,8 +1,4 @@ -use symbolica::{ - atom::{Atom, FunctionBuilder}, - fun, - state::State, -}; +use symbolica::{atom::Atom, fun, state::State}; fn main() { let input = Atom::parse("x*(1+a)+x*5*y+f(5,x)+2+y^2+x^2 + x^3").unwrap(); diff --git a/src/atom.rs b/src/atom.rs index ccb2b4db..82fa4c62 100644 --- a/src/atom.rs +++ b/src/atom.rs @@ -683,11 +683,18 @@ impl FunctionBuilder { /// Create a new function by providing its name as the first argument, /// followed by the list of arguments. This macro uses [`FunctionBuilder`]. +/// +/// For example: +/// ``` +/// use symbolica::{atom::Atom, fun, state::State}; +/// let f_id = State::get_symbol("f"); +/// let f = fun!(f_id, Atom::new_num(3), &Atom::parse("x").unwrap()); +/// ``` #[macro_export] macro_rules! fun { - ($name:ident, $($id:expr),*) => { + ($name: expr, $($id: expr),*) => { { - let mut f = FunctionBuilder::new($name); + let mut f = $crate::atom::FunctionBuilder::new($name); $( f = f.add_arg(&$id); )+ @@ -1199,11 +1206,7 @@ impl> std::ops::Div for Atom { #[cfg(test)] mod test { - use crate::{ - atom::{Atom, FunctionBuilder}, - fun, - state::State, - }; + use crate::{atom::Atom, fun, state::State}; #[test] fn debug() { diff --git a/src/collect.rs b/src/collect.rs index e13959aa..d609d10e 100644 --- a/src/collect.rs +++ b/src/collect.rs @@ -631,11 +631,7 @@ impl<'a> AtomView<'a> { #[cfg(test)] mod test { - use crate::{ - atom::{Atom, FunctionBuilder}, - fun, - state::State, - }; + use crate::{atom::Atom, fun, state::State}; #[test] fn coefficient_list() { diff --git a/src/domains/rational_polynomial.rs b/src/domains/rational_polynomial.rs index f895a3c6..0de54edd 100644 --- a/src/domains/rational_polynomial.rs +++ b/src/domains/rational_polynomial.rs @@ -95,6 +95,34 @@ where } } +impl RationalPolynomial +where + Self: FromNumeratorAndDenominator, +{ + pub fn unify_variables(&mut self, other: &mut Self) { + assert_eq!(self.numerator.variables, self.denominator.variables); + assert_eq!(other.numerator.variables, other.denominator.variables); + + // this may require a new normalization of the denominator + self.numerator.unify_variables(&mut other.numerator); + self.denominator.unify_variables(&mut other.denominator); + + *self = Self::from_num_den( + self.numerator.clone(), + self.denominator.clone(), + &self.numerator.field, + false, + ); + + *other = Self::from_num_den( + other.numerator.clone(), + other.denominator.clone(), + &other.numerator.field, + false, + ); + } +} + impl RationalPolynomial { pub fn new(field: &R, var_map: Arc>) -> RationalPolynomial { let num = MultivariatePolynomial::new(field, None, var_map); @@ -110,14 +138,6 @@ impl RationalPolynomial { &self.numerator.variables } - pub fn unify_variables(&mut self, other: &mut Self) { - assert_eq!(self.numerator.variables, self.denominator.variables); - assert_eq!(other.numerator.variables, other.denominator.variables); - - self.numerator.unify_variables(&mut other.numerator); - self.denominator.unify_variables(&mut other.denominator); - } - pub fn is_zero(&self) -> bool { self.numerator.is_zero() } diff --git a/src/id.rs b/src/id.rs index 38e9a0b1..1f2d6035 100644 --- a/src/id.rs +++ b/src/id.rs @@ -1080,12 +1080,12 @@ impl Pattern { matched } - pub fn pattern_match<'a>( - &'a self, + pub fn pattern_match<'a: 'b, 'b>( + &'b self, target: AtomView<'a>, - conditions: &'a Condition, - settings: &'a MatchSettings, - ) -> PatternAtomTreeIterator<'a, 'a> { + conditions: &'b Condition, + settings: &'b MatchSettings, + ) -> PatternAtomTreeIterator<'a, 'b> { PatternAtomTreeIterator::new(self, target, conditions, settings) } } @@ -1601,6 +1601,16 @@ impl<'a, 'b> MatchStack<'a, 'b> { None } + /// Get a reference to all matches. + pub fn get_matches(&self) -> &[(Symbol, Match<'a>)] { + &self.stack + } + + /// Get the underlying matches `Vec`. + pub fn into_matches(self) -> Vec<(Symbol, Match<'a>)> { + self.stack + } + /// Return the length of the stack. #[inline] pub fn len(&self) -> usize { @@ -2444,8 +2454,8 @@ impl<'a: 'b, 'b> PatternAtomTreeIterator<'a, 'b> { pub fn new( pattern: &'b Pattern, target: AtomView<'a>, - conditions: &'a Condition, - settings: &'a MatchSettings, + conditions: &'b Condition, + settings: &'b MatchSettings, ) -> PatternAtomTreeIterator<'a, 'b> { PatternAtomTreeIterator { pattern, diff --git a/src/streaming.rs b/src/streaming.rs index 704f1a63..685d0329 100644 --- a/src/streaming.rs +++ b/src/streaming.rs @@ -632,7 +632,7 @@ mod test { let r = streamer.to_expression(); let res = Atom::parse("coeff((v3+2*v2*v3+v2*v3^2+v2^2)/(v2*v3))*v1").unwrap(); - assert_eq!(r, res); + assert_eq!(r - res, Atom::Zero); } #[test]