sim-nest 0.1.5

The SIM constellation umbrella facade: one crate that re-exports the runtime kernel, codecs, number domains, and libraries behind features.
Documentation
#[cfg(all(
    feature = "numbers-cas",
    feature = "numbers-cas-diff",
    feature = "numbers-cas-eval",
    feature = "numbers-i64"
))]
use sim_kernel::{Args, Expr, NumberLiteral, QuoteMode, Symbol};
#[cfg(all(
    feature = "numbers-cas",
    feature = "numbers-cas-diff",
    feature = "numbers-cas-eval",
    feature = "numbers-i64"
))]
use sim_lib_numbers_cas::CasExpr;

#[cfg(all(
    feature = "numbers-cas",
    feature = "numbers-cas-diff",
    feature = "numbers-cas-eval",
    feature = "numbers-i64"
))]
use super::support::eval_cx;

#[cfg(all(
    feature = "numbers-cas",
    feature = "numbers-cas-diff",
    feature = "numbers-cas-eval",
    feature = "numbers-i64"
))]
fn quoted(name: &str) -> Expr {
    Expr::Quote {
        mode: QuoteMode::Quote,
        expr: Box::new(Expr::Symbol(Symbol::new(name))),
    }
}

#[cfg(all(
    feature = "numbers-cas",
    feature = "numbers-cas-diff",
    feature = "numbers-cas-eval",
    feature = "numbers-i64"
))]
fn polynomial_expr() -> Expr {
    Expr::Call {
        operator: Box::new(Expr::Symbol(Symbol::new("+"))),
        args: vec![
            Expr::Call {
                operator: Box::new(Expr::Symbol(Symbol::new("*"))),
                args: vec![
                    Expr::Number(NumberLiteral {
                        domain: Symbol::qualified("numbers", "i64"),
                        canonical: "2".to_owned(),
                    }),
                    quoted("x"),
                ],
            },
            Expr::Call {
                operator: Box::new(Expr::Symbol(Symbol::new("^"))),
                args: vec![
                    quoted("x"),
                    Expr::Number(NumberLiteral {
                        domain: Symbol::qualified("numbers", "i64"),
                        canonical: "2".to_owned(),
                    }),
                ],
            },
        ],
    }
}

#[cfg(all(
    feature = "numbers-cas",
    feature = "numbers-cas-diff",
    feature = "numbers-cas-eval",
    feature = "numbers-i64"
))]
#[test]
fn diff_polynomial_matches_simplified_surface() {
    let mut cx = eval_cx();
    let polynomial = cx.eval_expr(polynomial_expr()).unwrap();
    let var = cx.factory().expr(quoted("x")).unwrap();
    let value = cx
        .call_function(&Symbol::new("diff"), Args::new(vec![polynomial, var]))
        .unwrap();
    assert_eq!(
        value.object().as_expr(&mut cx).unwrap(),
        Expr::List(vec![
            Expr::Symbol(Symbol::new("+")),
            Expr::Number(NumberLiteral {
                domain: Symbol::qualified("numbers", "i64"),
                canonical: "2".to_owned(),
            }),
            Expr::List(vec![
                Expr::Symbol(Symbol::new("*")),
                Expr::Number(NumberLiteral {
                    domain: Symbol::qualified("numbers", "i64"),
                    canonical: "2".to_owned(),
                }),
                Expr::Symbol(Symbol::new("x")),
            ]),
        ])
    );
}

#[cfg(all(
    feature = "numbers-cas",
    feature = "numbers-cas-diff",
    feature = "numbers-cas-eval",
    feature = "numbers-i64"
))]
#[test]
fn diff_sin_is_cos() {
    let mut cx = eval_cx();
    let derivative = sim_lib_numbers_cas_diff::diff_cas(
        &mut cx,
        &CasExpr::Op(Symbol::new("sin"), vec![CasExpr::Var(Symbol::new("x"))]),
        &Symbol::new("x"),
    )
    .unwrap();
    let value = sim_lib_numbers_cas::cas_expr_to_value(&mut cx, derivative).unwrap();
    assert_eq!(
        value.object().as_expr(&mut cx).unwrap(),
        Expr::List(vec![
            Expr::Symbol(Symbol::new("cos")),
            Expr::Symbol(Symbol::new("x")),
        ])
    );
}

#[cfg(all(
    feature = "numbers-cas",
    feature = "numbers-cas-diff",
    feature = "numbers-cas-eval",
    feature = "numbers-i64"
))]
#[test]
fn diff_product_with_respect_to_x_is_y() {
    let mut cx = eval_cx();
    let product = cx
        .eval_expr(Expr::Call {
            operator: Box::new(Expr::Symbol(Symbol::new("*"))),
            args: vec![quoted("x"), quoted("y")],
        })
        .unwrap();
    let var = cx.factory().expr(quoted("x")).unwrap();
    let value = cx
        .call_function(&Symbol::new("diff"), Args::new(vec![product, var]))
        .unwrap();
    assert_eq!(
        value.object().as_expr(&mut cx).unwrap(),
        Expr::Symbol(Symbol::new("y"))
    );
}

#[cfg(all(
    feature = "numbers-cas",
    feature = "numbers-cas-diff",
    feature = "numbers-cas-eval",
    feature = "numbers-i64"
))]
#[test]
fn eval_cas_uses_current_env_and_derivative_evaluates() {
    let mut cx = eval_cx();
    let polynomial = cx.eval_expr(polynomial_expr()).unwrap();
    let var = cx.factory().expr(quoted("x")).unwrap();
    let derivative = cx
        .call_function(&Symbol::new("diff"), Args::new(vec![polynomial, var]))
        .unwrap();
    let x = cx
        .factory()
        .number_literal(Symbol::qualified("numbers", "i64"), "3".to_owned())
        .unwrap();
    cx.env_mut().define(Symbol::new("x"), x);
    let value = cx
        .call_function(&Symbol::new("eval-cas"), Args::new(vec![derivative]))
        .unwrap();
    assert_eq!(
        value.object().as_expr(&mut cx).unwrap(),
        Expr::Number(NumberLiteral {
            domain: Symbol::qualified("numbers", "i64"),
            canonical: "8".to_owned(),
        })
    );
}