Module ad

Module ad 

Source
Expand description

Taylor mode forward automatic differentiation with const-generic Jet<N> type

§Overview

This module provides a const-generic Jet<N> struct for Taylor-mode forward AD of arbitrary order N. The struct stores normalized Taylor coefficients:

Jet { value: c_0, deriv: [c_1, c_2, ..., c_N] }

where $c_k = f^{(k)}(a) / k!$ is the $k$-th normalized Taylor coefficient evaluated at the expansion point $a$. This normalization eliminates binomial coefficients from all arithmetic recurrences.

§Type Aliases

  • Dual = Jet<1> — first-order forward AD (value + first derivative)
  • HyperDual = Jet<2> — second-order forward AD (value + first + second derivative)

§Constructors

  • Jet::var(x) — independent variable at point x (deriv[0] = 1)
  • Jet::constant(x) — constant (all derivatives zero)
  • Jet::new(value, deriv) — raw constructor
  • ad0(x)Jet<0> constant (backward compat)
  • ad1(x, dx)Jet<1> with first derivative (backward compat)
  • ad2(x, dx, ddx)Jet<2> with first and second derivatives (backward compat)

§Accessors

  • .value() / .x() — $f(a)$
  • .dx() — $f’(a)$
  • .ddx() — $f’’(a)$
  • .derivative(k) — $f^{(k)}(a)$ (raw factorial-scaled derivative)
  • .taylor_coeff(k) — normalized Taylor coefficient $c_k$

§Implemented Operations

  • Add, Sub, Mul, Div (Jet op Jet, Jet op f64, f64 op Jet)
  • Neg
  • ExpLogOps: exp, ln, log, log2, log10
  • PowOps: powi, powf, pow, sqrt
  • TrigOps: sin_cos, sin, cos, tan, sinh, cosh, tanh, asin, acos, atan, asinh, acosh, atanh

§Usage

extern crate peroxide;
use peroxide::fuga::*;

fn main() {
    // First derivative of f(x) = x^2 at x = 2
    let x = Jet::<1>::var(2.0);
    let y = x.powi(2);
    assert_eq!(y.value(), 4.0);
    assert_eq!(y.dx(), 4.0);  // f'(2) = 2*2 = 4

    // Second derivative using HyperDual
    let x2 = HyperDual::new(2.0, [1.0, 0.0]);
    let y2 = x2.powi(2);
    assert_eq!(y2.value(), 4.0);
    assert_eq!(y2.dx(), 4.0);   // f'(2) = 4
    assert_eq!(y2.ddx(), 2.0);  // f''(2) = 2
}

§Higher-order derivatives

extern crate peroxide;
use peroxide::fuga::*;

fn main() {
    // 5th derivative of x^5 at x = 1
    let x = Jet::<5>::var(1.0);
    let y = x.powi(5);
    assert_eq!(y.derivative(5), 120.0);  // 5! = 120
}

§Using the #[ad_function] macro

extern crate peroxide;
use peroxide::fuga::*;

#[ad_function]
fn f(x: f64) -> f64 {
    x.sin() + x.powi(2)
}

fn main() {
    // f_grad and f_hess are generated automatically
    let grad = f_grad(1.0);   // f'(1) = cos(1) + 2
    let hess = f_hess(1.0);   // f''(1) = -sin(1) + 2

    assert!((grad - (1.0_f64.cos() + 2.0)).abs() < 1e-10);
    assert!((hess - (-1.0_f64.sin() + 2.0)).abs() < 1e-10);
}

§Generic functions with Real trait

extern crate peroxide;
use peroxide::fuga::*;

fn quadratic<T: Real>(x: T) -> T {
    x.powi(2) + x * 3.0 + T::from_f64(1.0)
}

fn main() {
    // Works with both f64 and AD (= Jet<2>)
    let val = quadratic(2.0_f64);                // 11.0
    let jet = quadratic(AD1(2.0, 1.0));
    assert_eq!(val, 11.0);                       // f(2) = 4 + 6 + 1
    assert_eq!(jet.value(), 11.0);               // f(2) = 11
    assert_eq!(jet.dx(), 7.0);                   // f'(2) = 2*2 + 3
}

§Jacobian computation

extern crate peroxide;
use peroxide::fuga::*;

fn main() {
    // Jacobian of f(x,y) = [x - y, x + 2*y] at (1, 1)
    let x = vec![1.0, 1.0];
    let j = jacobian(f, &x);
    j.print();
    //       c[0] c[1]
    // r[0]     1   -1
    // r[1]     1    2
}

fn f(xs: &Vec<AD>) -> Vec<AD> {
    let x = xs[0];
    let y = xs[1];
    vec![x - y, x + 2.0 * y]
}

§Backward-compatible constructors

extern crate peroxide;
use peroxide::fuga::*;

fn main() {
    // These work just like the old AD1/AD2 constructors
    let a = AD1(2.0, 1.0);   // value=2, f'=1
    let b = AD2(4.0, 4.0, 2.0);  // x^2 at x=2

    assert_eq!(a.x(), 2.0);
    assert_eq!(b.dx(), 4.0);
    assert_eq!(b.ddx(), 2.0);

    // New constructors (equivalent)
    let c = Jet::<1>::var(2.0);  // Same as Dual var at x=2
    assert_eq!(c.dx(), 1.0);     // dx/dx = 1 for independent variable
}

§Accuracy: Jet<N> vs Finite Differences

Jet<N> computes derivatives to machine precision because it propagates exact Taylor coefficients through the computation graph. In contrast, finite difference methods suffer from both truncation and cancellation errors that worsen rapidly at higher derivative orders.

The plot below compares the relative error of Jet<N> against central finite differences ($h = 10^{-4}$) for $f(x) = \sin(x)$ at $x = 1.0$, across derivative orders 1–8:

Derivative Accuracy

Jet<N> (blue) stays at $\sim 10^{-15}$ (machine epsilon) for all orders, while finite differences (green) degrade from $\sim 10^{-9}$ at order 1 to $> 10^{0}$ at order 4.

§Taylor Series Convergence

Since Jet<N> stores normalized Taylor coefficients $c_k = f^{(k)}(a)/k!$, you can directly reconstruct the Taylor polynomial of any function:

$$T_N(x) = c_0 + c_1 (x-a) + c_2 (x-a)^2 + \cdots + c_N (x-a)^N$$

The plot below shows the Taylor polynomial of $\sin(x)$ around $x = 0$ for increasing truncation orders $N = 1, 3, 5, 7, 9$:

Taylor Convergence

As $N$ increases, the Taylor polynomial converges to the exact $\sin(x)$ curve over a wider interval.

Structs§

ADFn
Generic AD function wrapper.
Jet
Const-generic Taylor-mode forward AD type.

Traits§

ADVec
Backward compatibility trait: provides to_ad_vec and to_f64_vec on vector types.
JetVec
Trait for converting between Vec<f64> and Vec<Jet<1>>.

Functions§

AD0
Backward compatibility constructor: AD0(x) creates a zero-derivative Jet<2> constant.
AD1
Backward compatibility constructor: AD1(x, dx) creates a Jet<2> with given first derivative.
AD2
Backward compatibility constructor: AD2(x, dx, ddx) creates a Jet<2> with given derivatives.
ad0
Create a Jet<0> constant (zero-order, value only).
ad1
Create a Jet<1> with value and first derivative. dx is the raw first derivative $f’(a)$; stored as deriv[0] $= dx / 1! = dx$.
ad2
Create a Jet<2> with value, first derivative, and second derivative. ddx is the raw second derivative $f’‘(a)$; stored internally as deriv[1] $= f’’(a) / 2!$.

Type Aliases§

AD
Backward compatibility alias: AD is now Jet<2>.
Dual
First-order forward AD: stores value and first derivative.
HyperDual
Second-order forward AD: stores value, first derivative, and second derivative $/, 2!$.