ihateintegrals 0.1.2

A computer algebra library for solving integrals.
Documentation
use std::rc::Rc;

use crate::{
    argument::Argument,
    convenience_expressions::i,
    expressions::{product::product_of_iter, Expression},
};

use super::DerivationRule;

pub struct EvaluateProducts {}

impl DerivationRule for EvaluateProducts {
    fn apply(&self, input: Expression) -> Vec<(Expression, Rc<Argument>)> {
        let product = match input {
            Expression::Product(ref p) => p,
            _ => return vec![],
        };

        let (ints, non_ints): (Vec<&Expression>, Vec<&Expression>) = product
            .factors()
            .iter()
            .partition(|expression| matches!(expression, Expression::Integer(_)));

        if ints.len() <= 1 {
            return vec![];
        }

        let product = ints
            .into_iter()
            .map(|i| match i {
                Expression::Integer(i) => i.value(),
                _ => panic!(),
            })
            .product();

        let result = product_of_iter(
            &mut [i(product)]
                .into_iter()
                .chain(non_ints.into_iter().cloned()),
        );

        vec![(
            result,
            Argument::new(
                String::from("Evaluate multiplication"),
                vec![input],
                self.name(),
            ),
        )]
    }
    fn name(&self) -> String {
        String::from("EvaluateProducts")
    }
}

#[cfg(test)]
mod tests {
    use super::EvaluateProducts;
    use crate::{
        convenience_expressions::{i, v},
        derivation_rules::DerivationRule,
        expressions::product::product_of,
    };

    #[test]
    fn test_1() {
        let rule = EvaluateProducts {};

        let start = product_of(&[i(1), i(2), i(2), v("a")]);
        let result = rule.apply(start).first().unwrap().0.clone();

        assert_eq!(result, product_of(&[i(4), v("a")]));
    }
}