amari-dual 0.15.1

Dual number automatic differentiation
Documentation

amari-dual

Dual number automatic differentiation for efficient gradient computation.

Overview

amari-dual implements dual numbers for forward-mode automatic differentiation. Dual numbers extend real numbers with an infinitesimal unit ε where ε² = 0, enabling exact derivative computation without numerical approximation or computational graphs.

Features

  • DualNumber: Single-variable automatic differentiation
  • MultiDualNumber: Multi-variable gradient computation
  • DualMultivector: Integration with geometric algebra
  • Mathematical Functions: Differentiable sin, cos, exp, log, and more
  • High-Precision Support: Optional extended precision arithmetic
  • no_std Support: Usable in embedded and WASM environments

Installation

Add to your Cargo.toml:

[dependencies]
amari-dual = "0.12"

Feature Flags

[dependencies]
# Default features
amari-dual = "0.12"

# With serialization
amari-dual = { version = "0.12", features = ["serialize"] }

# With GPU acceleration
amari-dual = { version = "0.12", features = ["gpu"] }

# High-precision arithmetic
amari-dual = { version = "0.12", features = ["high-precision"] }

Quick Start

Single-Variable Differentiation

use amari_dual::DualNumber;

// Create a dual number: x = 3 with derivative seed 1
let x = DualNumber::new(3.0, 1.0);

// Compute f(x) = x²
let f = x * x;

// Extract value and derivative
println!("f(3) = {}", f.value());       // 9.0
println!("f'(3) = {}", f.derivative()); // 6.0 (2x at x=3)

Multi-Variable Gradients

use amari_dual::MultiDualNumber;

// Variables: x=2, y=3
// Seed x with [1,0], y with [0,1] for gradient computation
let x = MultiDualNumber::new(2.0, vec![1.0, 0.0]);
let y = MultiDualNumber::new(3.0, vec![0.0, 1.0]);

// Compute f(x,y) = x² + xy
let f = x.clone() * x.clone() + x * y;

// Get the gradient
let gradient = f.get_gradient(); // [2x + y, x] = [7, 2]

Constants

use amari_dual::DualNumber;

// For constants (derivative = 0)
let c = DualNumber::constant(5.0);

// Multiply: f(x) = 5x
let x = DualNumber::new(2.0, 1.0);
let result = c * x;
// value = 10, derivative = 5

Mathematical Background

Dual Numbers

A dual number has the form:

a + εb   where ε² = 0

Arithmetic operations:

  • Addition: (a + εb) + (c + εd) = (a + c) + ε(b + d)
  • Multiplication: (a + εb) × (c + εd) = ac + ε(ad + bc)

Automatic Differentiation

When we evaluate f(a + ε), we get:

f(a + ε) = f(a) + εf'(a)

This gives us both the value f(a) and derivative f'(a) in a single pass through the computation.

Advantages

Approach Accuracy Memory Complexity
Finite Differences O(h) error O(1) O(n) evaluations
Symbolic Exact O(expression) Can explode
Dual Numbers Exact O(1) O(1) overhead

Key Types

DualNumber

Single-variable dual number for computing f and f':

use amari_dual::DualNumber;

let x = DualNumber::new(value, derivative_seed);
let value = x.value();
let deriv = x.derivative();

MultiDualNumber

Multi-variable dual number for computing gradients:

use amari_dual::MultiDualNumber;

let x = MultiDualNumber::new(value, gradient_seeds);
let value = x.get_value();
let gradient = x.get_gradient();
let n_vars = x.n_vars();

DualMultivector

Dual numbers integrated with geometric algebra:

use amari_dual::DualMultivector;

// Differentiable geometric algebra operations
let mv = DualMultivector::new(/* ... */);

Modules

Module Description
types DualNumber and MultiDualNumber implementations
functions Differentiable mathematical functions (sin, cos, exp, log)
multivector Integration with geometric algebra multivectors
verified Phantom types for compile-time verification
error Error types for dual operations

Differentiable Functions

use amari_dual::{DualNumber, functions};

let x = DualNumber::new(1.0, 1.0);

// Trigonometric
let sin_x = functions::sin(x);  // sin(1), cos(1)
let cos_x = functions::cos(x);  // cos(1), -sin(1)

// Exponential and logarithm
let exp_x = functions::exp(x);  // e¹, e¹
let ln_x = functions::ln(x);    // ln(1)=0, 1/1=1

// Power
let x_squared = x * x;          // 1, 2

v0.12.0 API Changes

The API was updated in v0.12.0 for better encapsulation:

// Before (v0.11.x)
let x = DualNumber { real: 3.0, dual: 1.0 };
let value = x.real;
let deriv = x.dual;

// After (v0.12.0+)
let x = DualNumber::new(3.0, 1.0);
let value = x.value();
let deriv = x.derivative();

Performance

  • Zero overhead: Dual arithmetic has minimal cost over regular arithmetic
  • Single pass: Compute value and derivative together
  • Cache friendly: Data locality for dual number pairs
  • SIMD potential: Parallel computation of value and derivative

Use Cases

  • Machine Learning: Backpropagation and gradient descent
  • Scientific Computing: Sensitivity analysis
  • Optimization: Gradient-based methods
  • Physics Simulation: Computing forces from potentials

License

Licensed under either of Apache License, Version 2.0 or MIT License at your option.

Part of Amari

This crate is part of the Amari mathematical computing library.