pub fn from_expr(
        expr: RcExpr,
        relative_to: Option<RcExpr>,
    ) -> Result<(Self, Option<RcExpr>), String> {
        // First, let's try to flatten the expression which will automatically combine terms for
        // us. If the expr is an addition or subtraction, this will also normalize it to an
        // addition.
        let expr = flatten_expr(expr);
        // Next, let's unroll the addition into its individual polynomial parts.
        // TODO: we should really rename this, it overlaps with `flatten_expr`.
        // TODO: we can more efficient by getting the unrolled args during flattening, skipping
        //       this step
        let poly_parts = get_flattened_binary_args(expr, BinaryOperator::Plus);

        let mut uniq_terms = HashSet::<RcExpr>::new();
        // Polynomial degree -> coefficient for that term
        let mut degree_coeffs = HashMap::<usize, isize>::new();
        if let Some(ref term) = relative_to {
            uniq_terms.insert(term.clone());
        }
        let mut konst_f64 = 0.;
        for poly_part in poly_parts.iter() {
            match poly_part.as_ref() {
                Expr::Const(c) => konst_f64 += c,
                Expr::BinaryExpr(BinaryExpr {
                    op: BinaryOperator::Mult,
                    lhs,
                    rhs,
                }) if lhs.is_const() || rhs.is_const() => {
                    let (c_f64, term) = if lhs.is_const() {
                        (lhs.get_const().unwrap(), rhs)
                    } else {
                        (rhs.get_const().unwrap(), lhs)
                    };
                    let coeff = c_f64 as isize;
                    if (coeff as f64 - c_f64).abs() > std::f64::EPSILON {
                        // Currently we only support `isize` for polynomial coefficients, so bail
                        // out if the conversion is lossy.
                        return Err(format!("Expected an integer coefficient for {}", poly_part));
                    }

                    // Get the raw term and exponent.
                    let (term, pow) = term_and_pow_from_expr(term.clone())?;

                    degree_coeffs.insert(pow, coeff);
                    uniq_terms.insert(term);
                }

                // TODO: we should probably be smarter with other terms, and even multiplication.
                _ => {
                    let (term, pow) = term_and_pow_from_expr(poly_part.clone())?;
                    // We couldn't unroll the coefficient in the above match, so make it one here.
                    degree_coeffs.insert(pow, 1);
                    uniq_terms.insert(term);
                }
            }

            if uniq_terms.len() > 1 {
                // Polynomials should be based on a singular unique term.
                return Err(format!(
                    "Expected a singular unique term, found {}: {:#?}",
                    uniq_terms.len(),
                    uniq_terms
                ));
            }
        }

        let konst = konst_f64 as isize;
        if (konst as f64 - konst_f64).abs() > std::f64::EPSILON {
            return Err(format!("Expected an integer constant, got {}", konst_f64));
        }

        let degree = degree_coeffs.keys().max();
        match degree {
            // There are no explicit terms in the polynomial, just return the constant or an
            // empty polynomial.
            None if konst != 0 => Ok((poly![konst], None)),
            None => Ok((poly![], None)),
            Some(degree) => {
                let len = degree + 1;
                let mut poly = vec![0; len];
                poly[0] = konst;
                for (pow, coeff) in degree_coeffs.into_iter() {
                    poly[pow] = coeff;
                }
                Ok((Self::new(poly), uniq_terms.into_iter().next()))
            }
        }
    }
/// Transforms an expression into a polynomial relative to some term.
/// If `relative_to` is not none, the constructed polynomial will be relative to that term.
/// Otherwise, the polynomial will be relative to the term in the expression sequence.
///
/// If transformation is successful, the return value is a tuple of (polynomial, relative term).
/// Transformation may fail for a number of reasons, including the expression containing a
/// non-unique term, consisting of non-integer coefficients, or non-integer exponents.
///
/// ## Examples
///
/// ```ignore
/// from_expr("x + 2x^2", None) == Some(poly![0, 1, 2], Some(Var("x")))
/// from_expr("5", None) == Some(poly![5], None)
/// from_expr("x + 2x^2", Some(Var("x"))) == Some(poly![0, 1, 2], Some(Var("x")))
/// from_expr("y + 2y^2", Some(Var("x"))) == None
/// from_expr("2.5x", None) == None
/// from_expr("x^{2.5}", None) == None
/// from_expr("x^{-2}", None) == None
/// ```
Transforms an expression into a polynomial relative to some term.
If `relative_to` is not none, the constructed polynomial will be relative to that term.
Otherwise, the polynomial will be relative to the term in the expression sequence.

If transformation is successful, the return value is a tuple of (polynomial, relative term).
Transformation may fail for a number of reasons, including the expression containing a
non-unique term, consisting of non-integer coefficients, or non-integer exponents.
Transforms an expression into a polynomial relative to some term . If ` relative_to ` is not none the constructed polynomial will be relative to that term . Otherwise the polynomial will be relative to the term in the expression sequence . If transformation is successful the return value is a tuple of ( polynomial relative term ) . Transformation may fail for a number of reasons including the expression containing a non - unique term consisting of non - integer coefficients or non - integer exponents .
pub fn from_expr(
        expr: RcExpr,
        relative_to: Option<RcExpr>,
    ) -> Result<(Self, Option<RcExpr>), String> {
        // First, let's try to flatten the expression which will automatically combine terms for
        // us. If the expr is an addition or subtraction, this will also normalize it to an
        // addition.
        let expr = flatten_expr(expr);
        // Next, let's unroll the addition into its individual polynomial parts.
        // TODO: we should really rename this, it overlaps with `flatten_expr`.
        // TODO: we can more efficient by getting the unrolled args during flattening, skipping
        //       this step
        let poly_parts = get_flattened_binary_args(expr, BinaryOperator::Plus);
        let mut uniq_terms = HashSet::<RcExpr>::new();
        // Polynomial degree -> coefficient for that term
        let mut degree_coeffs = HashMap::<usize, isize>::new();
        if let Some(ref term) = relative_to {
            uniq_terms.insert(term.clone());
        }
        let mut konst_f64 = 0.;
        for poly_part in poly_parts.iter() {
            match poly_part.as_ref() {
                Expr::Const(c) => konst_f64 += c,
                Expr::BinaryExpr(BinaryExpr {
                    op: BinaryOperator::Mult,
                    lhs,
                    rhs,
                }) if lhs.is_const() || rhs.is_const() => {
                    let (c_f64, term) = if lhs.is_const() {
                        (lhs.get_const().unwrap(), rhs)
                    } else {
                        (rhs.get_const().unwrap(), lhs)
                    };
                    let coeff = c_f64 as isize;
                    if (coeff as f64 - c_f64).abs() > std::f64::EPSILON {
                        // Currently we only support `isize` for polynomial coefficients, so bail
                        // out if the conversion is lossy.
                        return Err(format!("Expected an integer coefficient for {}", poly_part));
                    }
                    // Get the raw term and exponent.
                    let (term, pow) = term_and_pow_from_expr(term.clone())?;
                    degree_coeffs.insert(pow, coeff);
                    uniq_terms.insert(term);
                }
                // TODO: we should probably be smarter with other terms, and even multiplication.
                _ => {
                    let (term, pow) = term_and_pow_from_expr(poly_part.clone())?;
                    // We couldn't unroll the coefficient in the above match, so make it one here.
                    degree_coeffs.insert(pow, 1);
                    uniq_terms.insert(term);
                }
            }
            if uniq_terms.len() > 1 {
                // Polynomials should be based on a singular unique term.
                return Err(format!(
                    "Expected a singular unique term, found {}: {:#?}",
                    uniq_terms.len(),
                    uniq_terms
                ));
            }
        }
        let konst = konst_f64 as isize;
        if (konst as f64 - konst_f64).abs() > std::f64::EPSILON {
            return Err(format!("Expected an integer constant, got {}", konst_f64));
        }
        let degree = degree_coeffs.keys().max();
        match degree {
            // There are no explicit terms in the polynomial, just return the constant or an
            // empty polynomial.
            None if konst != 0 => Ok((poly![konst], None)),
            None => Ok((poly![], None)),
            Some(degree) => {
                let len = degree + 1;
                let mut poly = vec![0; len];
                poly[0] = konst;
                for (pow, coeff) in degree_coeffs.into_iter() {
                    poly[pow] = coeff;
                }
                Ok((Self::new(poly), uniq_terms.into_iter().next()))
            }
        }
    }
pub fn from_expr ( expr : RcExpr , relative_to : Option < RcExpr > , ) -> Result < ( Self , Option < RcExpr > ) , String > { // First, let's try to flatten the expression which will automatically combine terms for // us. If the expr is an addition or subtraction, this will also normalize it to an // addition. let expr = flatten_expr ( expr ) ; // Next, let's unroll the addition into its individual polynomial parts. // TODO: we should really rename this, it overlaps with `flatten_expr`. // TODO: we can more efficient by getting the unrolled args during flattening, skipping //       this step let poly_parts = get_flattened_binary_args ( expr , BinaryOperator :: Plus ) ; let mut uniq_terms = HashSet :: < RcExpr > :: new ( ) ; // Polynomial degree -> coefficient for that term let mut degree_coeffs = HashMap :: < usize , isize > :: new ( ) ; if let Some ( ref term ) = relative_to { uniq_terms . insert ( term . clone ( ) ) ; } let mut konst_f64 = 0. ; for poly_part in poly_parts . iter ( ) { match poly_part . as_ref ( ) { Expr :: Const ( c ) => konst_f64 += c , Expr :: BinaryExpr ( BinaryExpr { op : BinaryOperator :: Mult , lhs , rhs , } ) if lhs . is_const ( ) || rhs . is_const ( ) => { let ( c_f64 , term ) = if lhs . is_const ( ) { ( lhs . get_const ( ) . unwrap ( ) , rhs ) } else { ( rhs . get_const ( ) . unwrap ( ) , lhs ) } ; let coeff = c_f64 as isize ; if ( coeff as f64 - c_f64 ) . abs ( ) > std :: f64 :: EPSILON { // Currently we only support `isize` for polynomial coefficients, so bail // out if the conversion is lossy. return Err ( format ! ( " " poly_part ) ) ; } // Get the raw term and exponent. let ( term , pow ) = term_and_pow_from_expr ( term . clone ( ) ) ? ; degree_coeffs . insert ( pow , coeff ) ; uniq_terms . insert ( term ) ; } // TODO: we should probably be smarter with other terms, and even multiplication. _ => { let ( term , pow ) = term_and_pow_from_expr ( poly_part . clone ( ) ) ? ; // We couldn't unroll the coefficient in the above match, so make it one here. degree_coeffs . insert ( pow , 1 ) ; uniq_terms . insert ( term ) ; } } if uniq_terms . len ( ) > 1 { // Polynomials should be based on a singular unique term. return Err ( format ! ( " " uniq_terms len ( ) uniq_terms ) ) ; } } let konst = konst_f64 as isize ; if ( konst as f64 - konst_f64 ) . abs ( ) > std :: f64 :: EPSILON { return Err ( format ! ( " " konst_f64 ) ) ; } let degree = degree_coeffs . keys ( ) . max ( ) ; match degree { // There are no explicit terms in the polynomial, just return the constant or an // empty polynomial. None if konst != 0 => Ok ( ( poly ! [ konst ] , None ) ) , None => Ok ( ( poly ! [ ] , None ) ) , Some ( degree ) => { let len = degree + 1 ; let mut poly = vec ! [ 0 len ] ; poly [ 0 ] = konst ; for ( pow , coeff ) in degree_coeffs . into_iter ( ) { poly [ pow ] = coeff ; } Ok ( ( Self :: new ( poly ) , uniq_terms . into_iter ( ) . next ( ) ) ) } } }
Transforms an expression into a polynomial relative to some term.
Transforms an expression into a polynomial relative to some term .
expr
RcExpr
relative_to
Option<RcExpr>
expr
RcExpr
relative_to
Option<RcExpr>
examples
None