Dimensional Analysis
symplex::units provides compile-time dimensional analysis: a quantity’s dimension is part of its Rust type, so adding a Mass to a Length does not compile, and differentiating a Length with respect to a Time yields a Velocity. Underneath, every quantity is an Ex in SI base units, so all the symbolic machinery still applies.
Quantity types
Qty<D> is generic over a type-level dimension Dim<L, M, T, I, Θ, N, J> (powers of length, mass, time, current, temperature, amount, luminous intensity, as typenum integers). Thirty named aliases cover the common cases: Length, Mass, Time, Current, Temperature, Area, Volume, Velocity, Acceleration, AngularVelocity, Frequency, Force, Energy, Torque, Power, Momentum, AngularMomentum, MomentOfInertia, Pressure, Stiffness, Damping, Voltage, Resistance, Inductance, Capacitance, Charge, MagneticFlux, Dimensionless, Angle, ….
use symplex::prelude::*;
use symplex::units::*;
fn main() {
let ctx = Context::new();
let m = Mass::symbol(&ctx, "m");
let a = Acceleration::symbol(&ctx, "a");
// The `: Force` annotation is checked by the compiler.
let f = dim!(ctx, Force: m * a);
println!("F = {f}"); // a*m [N]
let d = Length::symbol(&ctx, "d");
let w = dim!(ctx, Energy: f * d);
println!("W = {w}"); // a*d*m [J]
// Substitute and evaluate like any Ex
let f_num = f.subs(&m, &ctx.int(10)).subs(&a, &ctx.rational(981, 100)).eval();
println!("{f_num}"); // 981/10 [N]
println!("{}", f_num.eval_f64().unwrap()); // 98.1
}
Mass + Length is a type error; Mass * Acceleration is a Force; Energy / Time is a Power. Multiplication and division of quantities compute the resulting dimension at the type level.
Typed calculus
diff_wrt(&Time) divides the dimension by time; integrate_wrt multiplies. Build the formula with expr! on raw symbols and wrap it with from_ex:
use symplex::prelude::*;
use symplex::units::*;
fn main() {
let ctx = Context::new();
symplex::syms!(ctx; g, t); // raw symbols for expr!
let t_var = Time::symbol(&ctx, "t");
let x = Length::from_ex(expr!(ctx, 1 / 2 * g * t ^ 2));
let v: Velocity = x.diff_wrt(&t_var); // d(Length)/d(Time)
let acc: Acceleration = v.diff_wrt(&t_var);
println!("{x}\n{v}\n{acc}"); // 1/2*g*t^2 [m] g*t [m/s] g [m/s²]
println!("{}", acc.inner()); // the underlying Ex: g
}
Exact conversions
Named constructors convert from other units with exact rational factors: Length::inches(&x), Length::miles(&x), Force::pound_force(&x), Pressure::psi(&x), Energy::btu(&x), Volume::us_gallons(&x), … (about 100 in total). The result is in SI.
use symplex::prelude::*;
use symplex::units::*;
fn main() {
let ctx = Context::new();
let one = ctx.int(1);
println!("{}", Length::inches(&one).eval()); // 127/5000 [m]
println!("{}", Force::pound_force(&one).eval()); // exact rational newtons
println!("{}", Pressure::psi(&one).eval());
println!("{}", Energy::btu(&one).eval());
println!("{:.6}", Volume::us_gallons(&one).eval_f64().unwrap() * 1000.0); // 3.785412 L
}
Physical constants
symplex::units::constants provides typed constants (speed_of_light, standard_gravity, planck_constant, boltzmann_constant, gravitational_constant, …) as exact PhysicalConstant nodes that display by name and evaluate on demand. cargo run --example physics_constants shows them.
Compile-time assertions
symplex::const_assert_dim! asserts a dimensional identity at compile time (for example that Energy equals Force × Length); symplex::units::inference infers dimensions of an untyped expression from a DimMap of symbol dimensions. See examples/units_physics.rs.
Code generation with uom
CodegenOptions::with_uom() (plus param_units / return_unit) annotates generated Rust functions with uom quantity types at the boundary (raw f64 inside). cargo run --example units_engineering shows a motor-design workflow ending in typed generated code.
Examples
cargo run --example units_physics # Newton, Ohm, pendulum, compile-time assertions
cargo run --example units_electrical # Circuit analysis with units
cargo run --example units_engineering # Motor design, imperial conversions, uom codegen
cargo run --example units_kinematics # Kinematics with typed calculus
cargo run --example units_lagrangian # Lagrangian mechanics with units