Skip to main content

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//!
33//! let registry = global_diff_registry().read().unwrap();
34//! let derivative = registry.apply(
35//!     &Symbol::new("ln-doctest"),
36//!     &[CasExpr::Var(Symbol::new("x"))],
37//!     &Symbol::new("x"),
38//! );
39//! assert!(matches!(derivative, Some(CasExpr::Op(_, _))));
40//! ```
41
42mod implementation;
43
44pub use implementation::{
45    CasDiffLib, CasDiffRegistry, DiffRule, diff_cas, diff_symbol, global_diff_registry,
46    integrate_cas, integrate_sym_symbol, register_diff_rule,
47};
48
49#[cfg(test)]
50mod tests;