Evaluating f(x) = x·sin(x) with Dual<f64> computes the value and exact derivative in a single pass — no finite differences, no symbolic engine. The green tangent line is the dual field: the slope, computed exactly for free.
// build the model let mut model = Sequential::<f64>::new(vec![ Box::new(Linear::new(240, 64, 42)), Box::new(Tanh::new()), Box::new(Linear::new(64, 64, 137)), Box::new(Tanh::new()), Box::new(Linear::new(64, 30, 256)), ]); // train let losses = Trainer::new(&mut model, ModuleAdam::new(0.005)) .loss_fn(|p, t| (cross_entropy_loss(p, t), cross_entropy_loss_grad(p, t))) .epochs(200) .fit(&mut loader);
Write your math once with S: Scalar. Swap the type to change what it does.
fn spring_energy<S: Scalar>( k: S, x: S ) -> S { k * x * x * S::from_f64(0.5) } spring_energy(10.0_f64, 0.3) // → 0.45
// same function, different type let x = Dual::var(0.3); spring_energy(10.0.into(), x) // → Dual { // val: 0.45, // energy // dual: 3.0, // ∂E/∂x = kx // }
Use only what you need.
Apple M-series, single-threaded. cargo bench -p tang-bench
Drop-in aliases. Minimal call-site changes.
| nalgebra | tang |
|---|---|
| Vector3<f64> | Vec3<f64> |
| Point3<f64> | Point3<f64> |
| Unit<Vector3> | Dir3<f64> |
| Matrix4<f64> | Mat4<f64> |
| UnitQuaternion | Quat<f64> |
| DVector<f64> | DVec<f64> |
| DMatrix<f64> | DMat<f64> |