| Crates.io | amari-dual |
| lib.rs | amari-dual |
| version | 0.17.0 |
| created_at | 2025-10-06 20:43:07.367649+00 |
| updated_at | 2026-01-11 22:32:40.488339+00 |
| description | Dual number automatic differentiation |
| homepage | https://github.com/justinelliottcobb/Amari |
| repository | https://github.com/justinelliottcobb/Amari |
| max_upload_size | |
| id | 1870822 |
| size | 154,917 |
Dual number automatic differentiation for efficient gradient computation.
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.
Add to your Cargo.toml:
[dependencies]
amari-dual = "0.12"
[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"] }
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)
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]
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
A dual number has the form:
a + εb where ε² = 0
Arithmetic operations:
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.
| 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 |
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();
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();
Dual numbers integrated with geometric algebra:
use amari_dual::DualMultivector;
// Differentiable geometric algebra operations
let mv = DualMultivector::new(/* ... */);
| 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 |
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
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();
Licensed under either of Apache License, Version 2.0 or MIT License at your option.
This crate is part of the Amari mathematical computing library.