symbolica 2.2.0

A blazing fast computer algebra system
Documentation
use symbolica::{
    atom::{Atom, AtomCore},
    parse, symbol,
};

#[test]
fn fibonacci() {
    // prepare all patterns
    let pattern = parse!("f(x_)").to_pattern();
    let rhs = parse!("f(x_ - 1) + f(x_ - 2)").to_pattern();
    let lhs_zero_pat = parse!("f(0)").to_pattern();
    let lhs_one_pat = parse!("f(1)").to_pattern();
    let rhs_one = Atom::num(1).to_pattern();

    // prepare the pattern restriction `x_ > 1`
    let restrictions = symbol!("x_").filter(|n| !n.is_one() && !n.is_zero());

    let mut target = parse!("f(10)");

    for _ in 0..9 {
        target = target
            .replace(&pattern)
            .when(&restrictions)
            .with(&rhs)
            .expand()
            .replace(&lhs_zero_pat)
            .with(&rhs_one)
            .replace(&lhs_one_pat)
            .with(&rhs_one);
    }

    assert_eq!(target, Atom::num(89));
}

#[test]
fn replace_once() {
    let expr = parse!("f(z)*f(f(x))*f(y)");
    let pat_expr = parse!("f(x_)");

    let rhs_expr = parse!("g(x_)");
    let rhs = rhs_expr.as_view().to_pattern();

    let pattern = pat_expr.as_view().to_pattern();

    let r: Vec<_> = expr.replace(&pattern).iter(&rhs).collect();

    let res = [
        "g(z)*f(y)*f(f(x))",
        "f(z)*g(y)*f(f(x))",
        "f(z)*f(y)*g(f(x))",
        "f(z)*f(y)*f(g(x))",
    ];

    let res = res.iter().map(|x| parse!(x)).collect::<Vec<_>>();

    assert_eq!(r, res);
}

#[test]
fn failed_nested_power_match_restores_wildcards() {
    let pattern = parse!("r(F_^(b__*(c__+d__*ivar_)^2), ivar_)")
        .to_pattern()
        .set_optional(symbol!("c__"))
        .set_optional(symbol!("d__"));

    let target = parse!("r(e^((b-2*c*x)^2*d^5), x)");
    let replaced = target
        .replace(&pattern)
        .with(parse!("hit(F_,b__,c__,d__,ivar_)").to_pattern());

    assert_eq!(replaced, parse!("hit(e,d^5,b,-2*c,x)"));
}