use symplex::prelude::*;
use symplex::units::*;
symplex::const_assert_dim!(
ConstDim::MASS.mul(ConstDim::ACCELERATION),
ConstDim::FORCE,
"F = ma: Mass * Acceleration must equal Force"
);
symplex::const_assert_dim!(
ConstDim::FORCE.mul(ConstDim::LENGTH),
ConstDim::ENERGY,
"E = Fd: Force * Length must equal Energy"
);
symplex::const_assert_dim!(
ConstDim::ENERGY.div(ConstDim::TIME),
ConstDim::POWER,
"P = E/t: Energy / Time must equal Power"
);
symplex::const_assert_dim!(
ConstDim::CURRENT.mul(ConstDim::RESISTANCE),
ConstDim::VOLTAGE,
"V = IR: Current * Resistance must equal Voltage"
);
symplex::const_assert_dim!(
ConstDim::CURRENT.mul(ConstDim::VOLTAGE),
ConstDim::POWER,
"P = IV: Current * Voltage must equal Power"
);
symplex::const_assert_dim!(
ConstDim::MOMENT_OF_INERTIA.mul(ConstDim::ANGULAR_ACCELERATION),
ConstDim::TORQUE,
"tau = I*alpha: MomentOfInertia * AngularAcceleration must equal Torque"
);
fn main() {
let ctx = Context::new();
println!("=== Symplex: Compile-Time Dimensional Analysis ===\n");
println!("── Newton's Second Law: F = ma ──");
let m = Mass::symbol(&ctx, "m");
let a = Acceleration::symbol(&ctx, "a");
let f = symplex::dim!(ctx, Force: m * a);
println!(" F = m·a = {}", f);
let f_num = f
.clone()
.subs(&m, &ctx.rational(10, 1))
.subs(&a, &ctx.rational(981, 100))
.eval();
println!(" F(m=10, a=9.81) = {}", f_num);
let d = Length::symbol(&ctx, "d");
let w = symplex::dim!(ctx, Energy: f * d);
println!(" W = F·d = {}", w);
let v = Velocity::symbol(&ctx, "v");
let p = symplex::dim!(ctx, Power: f * v);
println!(" P = F·v = {}", p);
println!("\n── Ohm's Law: V = IR, P = IV ──");
let i = Current::symbol(&ctx, "I");
let r = Resistance::symbol(&ctx, "R");
let volt = symplex::dim!(ctx, Voltage: i * r);
println!(" V = I·R = {}", volt);
let p_elec = symplex::dim!(ctx, Power: i * volt);
println!(" P = I·V = {}", p_elec);
let p_expanded = p_elec.clone().expand();
println!(" P expanded = {}", p_expanded);
let v_num = volt
.clone()
.subs(&i, &ctx.rational(3, 1))
.subs(&r, &ctx.rational(47, 1))
.eval();
println!(" V(I=3, R=47) = {}", v_num);
let p_num = p_elec
.subs(&i, &ctx.rational(3, 1))
.subs(&r, &ctx.rational(47, 1))
.eval();
println!(" P(I=3, R=47) = {}", p_num);
println!("\n── Pendulum: V = mgl(1 - cos θ) ──");
let m_pend = Mass::symbol(&ctx, "m");
let g = Acceleration::symbol(&ctx, "g");
let l = Length::symbol(&ctx, "l");
let theta = Angle::symbol(&ctx, "θ");
let weight = symplex::dim!(ctx, Force: m_pend * g);
let mgl = symplex::dim!(ctx, Energy: weight * l);
println!(" m·g·l = {}", mgl);
let cos_theta: Dimensionless = theta.cos();
let one_minus_cos: Dimensionless = Dimensionless::constant(&ctx, 1) - cos_theta;
let pe = symplex::dim!(ctx, Energy: mgl * one_minus_cos);
println!(" V = m·g·l·(1 - cos θ) = {}", pe);
let sin_theta: Dimensionless = Angle::symbol(&ctx, "θ").sin();
let torque_magnitude = symplex::dim!(ctx, Energy: mgl * sin_theta);
let tau: Torque = Torque::from_energy(-torque_magnitude);
println!(" τ = -m·g·l·sin(θ) = {}", tau);
println!("\n── Spring-Mass-Damper: F = -kx - cv + F_ext ──");
let k = Stiffness::symbol(&ctx, "k");
let x = Length::symbol(&ctx, "x");
let c = Damping::symbol(&ctx, "c");
let v_smd = Velocity::symbol(&ctx, "v");
let f_ext = Force::symbol(&ctx, "F_ext");
let f_spring = symplex::dim!(ctx, Force: -(k * x));
println!(" F_spring = -kx = {}", f_spring);
let f_damp = symplex::dim!(ctx, Force: -(c * v_smd));
println!(" F_damp = -cv = {}", f_damp);
let f_total: Force = &f_spring + &f_damp + f_ext.clone();
println!(" F_total = {}", f_total);
let m_smd = Mass::symbol(&ctx, "m");
let a_smd = symplex::dim!(ctx, Acceleration: f_total / m_smd);
println!(" a = F/m = {}", a_smd);
println!("\n── DC Motor Steady-State: V = R·I + Ke·ω ──");
let r_motor = Resistance::symbol(&ctx, "R");
let i_motor = Current::symbol(&ctx, "I");
let omega = AngularVelocity::symbol(&ctx, "ω");
let ke = MagneticFlux::symbol(&ctx, "Ke");
let v_resistive = symplex::dim!(ctx, Voltage: r_motor * i_motor);
println!(" V_R = R·I = {}", v_resistive);
let v_emf = symplex::dim!(ctx, Voltage: ke * omega);
println!(" V_emf = Ke·ω = {}", v_emf);
let v_supply: Voltage = &v_resistive + &v_emf;
println!(" V = R·I + Ke·ω = {}", v_supply);
let p_motor = symplex::dim!(ctx, Power: i_motor * v_supply);
println!(" P_in = I·V = {}", p_motor);
println!("\n── Unit Conversions ──");
let distance = Length::kilometers(&ctx.rational(5, 1));
println!(" 5 km = {}", distance);
let engine = Power::horsepower(&ctx.rational(300, 1));
println!(" 300 hp = {}", engine);
let boiling = Temperature::from_celsius(&ctx.rational(100, 1));
println!(" 100 °C = {}", boiling);
let body_temp = Temperature::from_fahrenheit(&ctx.rational(986, 10));
println!(" 98.6 °F = {}", body_temp);
let highway = Velocity::kilometers_per_hour(&ctx.rational(120, 1));
println!(" 120 km/h = {}", highway);
let one_g = Acceleration::standard_gravity(&ctx.int(1));
println!(" 1 g = {}", one_g);
let atm = Pressure::atmospheres(&ctx.rational(1, 1));
println!(" 1 atm = {}", atm);
println!("\n── Typed Calculus (DiffWrt / IntWrt) ──");
symplex::syms!(ctx; a, t);
let t_var = Time::symbol(&ctx, "t");
let position = Length::from_ex(expr!(ctx, 1 / 2 * a * t ^ 2));
println!(" x(t) = {}", position);
let velocity: Velocity = position.diff_wrt(&t_var);
println!(" v(t) = dx/dt = {}", velocity);
let acceleration: Acceleration = velocity.diff_wrt(&t_var);
println!(" a(t) = dv/dt = {}", acceleration);
let v_back: Velocity = acceleration.integrate_wrt(&t_var);
println!(" ∫ a dt = {} (Velocity)", v_back);
let x_back: Length = velocity.integrate_wrt(&t_var);
println!(" ∫ v dt = {} (Length)", x_back);
let energy = Energy::from_ex(expr!(ctx, 1 / 2 * a * t ^ 2));
let power: Power = energy.diff_wrt(&t_var);
println!(" dE/dt = {} (Power)", power);
let momentum = Momentum::from_ex(expr!(ctx, a * t));
let force_from_p: Force = momentum.diff_wrt(&t_var);
println!(" dp/dt = {} (Force)", force_from_p);
let charge = Charge::from_ex(expr!(ctx, a * t));
let current_from_q: Current = charge.diff_wrt(&t_var);
println!(" dQ/dt = {} (Current)", current_from_q);
let flux = MagneticFlux::from_ex(expr!(ctx, a * t));
let emf: Voltage = flux.diff_wrt(&t_var);
println!(" dΦ/dt = {} (Voltage — Faraday's law)", emf);
symplex::syms!(ctx; k, x);
let x_var = Length::symbol(&ctx, "x");
let spring_pe = Energy::from_ex(expr!(ctx, 1 / 2 * k * x ^ 2));
let spring_force: Force = spring_pe.diff_wrt(&x_var);
println!(" dU/dx = {} (Force from spring PE)", spring_force);
symplex::syms!(ctx; i_p, r_p);
let i_var = Current::symbol(&ctx, "i_p");
let power_expr = Power::from_ex(expr!(ctx, i_p ^ 2 * r_p));
let dp_di: Voltage = power_expr.diff_wrt(&i_var);
println!(" dP/dI = {} (Voltage)", dp_di);
println!("\n── assert_dim! Macro ──");
let m_check = Mass::symbol(&ctx, "m");
let a_check = Acceleration::symbol(&ctx, "a");
let f_check = symplex::dim!(ctx, Force: m_check * a_check);
println!(" dim!(ctx, Force: m*a) ✓ = {}", f_check);
let v_check = Velocity::symbol(&ctx, "v");
let t_check = Time::symbol(&ctx, "t");
let x_check = symplex::dim!(ctx, Length: v_check * t_check);
println!(" dim!(ctx, Length: v*t) ✓ = {}", x_check);
let p_check = symplex::dim!(ctx, Momentum: m_check * v_check);
println!(" dim!(ctx, Momentum: m*v) ✓ = {}", p_check);
let impulse = symplex::dim!(ctx, Momentum: m_check * v_check);
println!(" dim!(ctx, Momentum: m*v) ✓ = {}", impulse);
let l_check = Length::symbol(&ctx, "d");
let w_check = symplex::dim!(ctx, Energy: f_check * l_check);
println!(" dim!(ctx, Energy: F*d) ✓ = {}", w_check);
let pw_check = symplex::dim!(ctx, Power: w_check / t_check);
println!(" dim!(ctx, Power: E/t) ✓ = {}", pw_check);
println!("\n── Compile-Time Formula Verification (const_assert_dim!) ──");
println!(" ✓ F = ma (Mass × Acceleration = Force)");
println!(" ✓ E = Fd (Force × Length = Energy)");
println!(" ✓ P = E/t (Energy / Time = Power)");
println!(" ✓ V = IR (Current × Resistance = Voltage)");
println!(" ✓ P = IV (Current × Voltage = Power)");
println!(" ✓ τ = Iα (MomentOfInertia × AngularAcceleration = Torque)");
println!(" (All verified at compile time — see top of file)");
println!("\n── Physical Constants ──");
{
use symplex::units::constants;
let c = constants::speed_of_light(&ctx);
let m = Mass::symbol(&ctx, "m");
let energy = symplex::dim!(ctx, Energy: m * c * c);
println!(" E = mc² = {}", energy);
println!(" (Displays symbolically — 'c' not '299792458')");
println!(
" E(m=1kg) = {:.3e} J",
energy.subs(&m, &ctx.int(1)).eval_f64().unwrap()
);
}
println!("\n✓ All dimensional checks passed!");
}