sim_lib_numbers_cas_diff/lib.rs
1#![forbid(unsafe_code)]
2#![deny(missing_docs)]
3#![allow(deprecated)]
4
5//! Symbolic differentiation and integration over the `numbers/cas` expression
6//! tree: the `diff` and `integrate-sym` functions plus an extensible registry
7//! of per-operator differentiation rules.
8//!
9//! # Examples
10//!
11//! Teach the differentiator a new operator through the extensible rule
12//! registry, then look the rule up. Rules map an operator's arguments and the
13//! variable of differentiation to a derivative
14//! [`CasExpr`](sim_lib_numbers_cas::CasExpr):
15//!
16//! ```
17//! use sim_kernel::Symbol;
18//! use sim_lib_numbers_cas::CasExpr;
19//! use sim_lib_numbers_cas_diff::{global_diff_registry, register_diff_rule};
20//!
21//! // d/dx ln(x) = 1/x, expressed structurally as (/ 1 x).
22//! register_diff_rule(
23//! Symbol::new("ln-doctest"),
24//! Box::new(|args: &[CasExpr], _var: &Symbol| {
25//! let [arg] = args else { return None };
26//! Some(CasExpr::Op(
27//! Symbol::qualified("math", "div"),
28//! vec![CasExpr::Var(Symbol::new("1")), arg.clone()],
29//! ))
30//! }),
31//! )
32//! .unwrap();
33//!
34//! let registry = global_diff_registry().read().unwrap();
35//! let derivative = registry.apply(
36//! &Symbol::new("ln-doctest"),
37//! &[CasExpr::Var(Symbol::new("x"))],
38//! &Symbol::new("x"),
39//! );
40//! assert!(matches!(derivative, Some(CasExpr::Op(_, _))));
41//! ```
42
43mod implementation;
44
45pub use implementation::{
46 CasDiffLib, CasDiffRegistry, DiffRule, diff_cas, diff_symbol, global_diff_registry,
47 integrate_cas, integrate_sym_symbol, override_diff_rule, register_diff_rule,
48};
49
50/// Cookbook recipes for this lib, embedded at build time.
51pub static RECIPES: sim_cookbook::EmbeddedDir =
52 include!(concat!(env!("OUT_DIR"), "/cookbook_recipes.rs"));
53
54#[cfg(test)]
55mod tests;