use core::marker::PhantomData;
use typenum::{N1, N2, N3, P1, P2, P3, P4, Z0};
#[derive(Clone, Copy)]
pub struct Dim<L, M, T, I, Th, N, J> {
_phantom: PhantomData<(L, M, T, I, Th, N, J)>,
}
pub type DimensionlessDim = Dim<Z0, Z0, Z0, Z0, Z0, Z0, Z0>;
pub type AngleDim = Dim<Z0, Z0, Z0, Z0, Z0, Z0, Z0>;
pub type LengthDim = Dim<P1, Z0, Z0, Z0, Z0, Z0, Z0>;
pub type MassDim = Dim<Z0, P1, Z0, Z0, Z0, Z0, Z0>;
pub type TimeDim = Dim<Z0, Z0, P1, Z0, Z0, Z0, Z0>;
pub type CurrentDim = Dim<Z0, Z0, Z0, P1, Z0, Z0, Z0>;
pub type TemperatureDim = Dim<Z0, Z0, Z0, Z0, P1, Z0, Z0>;
pub type AreaDim = Dim<P2, Z0, Z0, Z0, Z0, Z0, Z0>;
pub type VolumeDim = Dim<P3, Z0, Z0, Z0, Z0, Z0, Z0>;
pub type VelocityDim = Dim<P1, Z0, N1, Z0, Z0, Z0, Z0>;
pub type AccelerationDim = Dim<P1, Z0, N2, Z0, Z0, Z0, Z0>;
pub type AngularVelocityDim = Dim<Z0, Z0, N1, Z0, Z0, Z0, Z0>; pub type AngularAccelerationDim = Dim<Z0, Z0, N2, Z0, Z0, Z0, Z0>;
pub type FrequencyDim = Dim<Z0, Z0, N1, Z0, Z0, Z0, Z0>;
pub type ForceDim = Dim<P1, P1, N2, Z0, Z0, Z0, Z0>;
pub type EnergyDim = Dim<P2, P1, N2, Z0, Z0, Z0, Z0>;
pub type TorqueDim = Dim<P2, P1, N2, Z0, Z0, Z0, Z0>; pub type PowerDim = Dim<P2, P1, N3, Z0, Z0, Z0, Z0>;
pub type MomentumDim = Dim<P1, P1, N1, Z0, Z0, Z0, Z0>;
pub type AngularMomentumDim = Dim<P2, P1, N1, Z0, Z0, Z0, Z0>;
pub type MomentOfInertiaDim = Dim<P2, P1, Z0, Z0, Z0, Z0, Z0>;
pub type PressureDim = Dim<N1, P1, N2, Z0, Z0, Z0, Z0>;
pub type StiffnessDim = Dim<Z0, P1, N2, Z0, Z0, Z0, Z0>;
pub type DampingDim = Dim<Z0, P1, N1, Z0, Z0, Z0, Z0>;
pub type VoltageDim = Dim<P2, P1, N3, N1, Z0, Z0, Z0>;
pub type ResistanceDim = Dim<P2, P1, N3, N2, Z0, Z0, Z0>;
pub type InductanceDim = Dim<P2, P1, N2, N2, Z0, Z0, Z0>;
pub type CapacitanceDim = Dim<N2, N1, P4, P2, Z0, Z0, Z0>;
pub type ChargeDim = Dim<Z0, Z0, P1, P1, Z0, Z0, Z0>;
pub type MagneticFluxDim = Dim<P2, P1, N2, N1, Z0, Z0, Z0>;
pub trait DimName {
fn dim_name() -> &'static str;
fn dim_symbol() -> &'static str;
}
macro_rules! impl_dim_name {
($dim_ty:ty, $name:expr, $symbol:expr) => {
impl DimName for $dim_ty {
#[inline]
fn dim_name() -> &'static str {
$name
}
#[inline]
fn dim_symbol() -> &'static str {
$symbol
}
}
};
}
impl_dim_name!(DimensionlessDim, "Dimensionless", "1");
impl_dim_name!(LengthDim, "Length", "m");
impl_dim_name!(MassDim, "Mass", "kg");
impl_dim_name!(TimeDim, "Time", "s");
impl_dim_name!(CurrentDim, "Current", "A");
impl_dim_name!(TemperatureDim, "Temperature", "K");
impl_dim_name!(AreaDim, "Area", "m²");
impl_dim_name!(VolumeDim, "Volume", "m³");
impl_dim_name!(VelocityDim, "Velocity", "m/s");
impl_dim_name!(AccelerationDim, "Acceleration", "m/s²");
impl_dim_name!(FrequencyDim, "Frequency", "Hz");
impl_dim_name!(AngularAccelerationDim, "AngularAcceleration", "rad/s²");
impl_dim_name!(ForceDim, "Force", "N");
impl_dim_name!(EnergyDim, "Energy", "J");
impl_dim_name!(PowerDim, "Power", "W");
impl_dim_name!(MomentumDim, "Momentum", "kg·m/s");
impl_dim_name!(AngularMomentumDim, "AngularMomentum", "kg·m²/s");
impl_dim_name!(MomentOfInertiaDim, "MomentOfInertia", "kg·m²");
impl_dim_name!(PressureDim, "Pressure", "Pa");
impl_dim_name!(StiffnessDim, "Stiffness", "N/m");
impl_dim_name!(DampingDim, "Damping", "N·s/m");
impl_dim_name!(VoltageDim, "Voltage", "V");
impl_dim_name!(ResistanceDim, "Resistance", "Ω");
impl_dim_name!(InductanceDim, "Inductance", "H");
impl_dim_name!(CapacitanceDim, "Capacitance", "F");
impl_dim_name!(ChargeDim, "Charge", "C");
impl_dim_name!(MagneticFluxDim, "MagneticFlux", "Wb");
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct ConstDim {
pub l: i8,
pub m: i8,
pub t: i8,
pub i: i8,
pub th: i8,
pub n: i8,
pub j: i8,
}
impl ConstDim {
#[inline]
pub const fn new(l: i8, m: i8, t: i8, i: i8, th: i8, n: i8, j: i8) -> Self {
Self {
l,
m,
t,
i,
th,
n,
j,
}
}
#[inline]
pub const fn mul(self, rhs: Self) -> Self {
Self {
l: self.l + rhs.l,
m: self.m + rhs.m,
t: self.t + rhs.t,
i: self.i + rhs.i,
th: self.th + rhs.th,
n: self.n + rhs.n,
j: self.j + rhs.j,
}
}
#[inline]
pub const fn div(self, rhs: Self) -> Self {
Self {
l: self.l - rhs.l,
m: self.m - rhs.m,
t: self.t - rhs.t,
i: self.i - rhs.i,
th: self.th - rhs.th,
n: self.n - rhs.n,
j: self.j - rhs.j,
}
}
#[inline]
pub const fn eq(self, rhs: Self) -> bool {
self.l == rhs.l
&& self.m == rhs.m
&& self.t == rhs.t
&& self.i == rhs.i
&& self.th == rhs.th
&& self.n == rhs.n
&& self.j == rhs.j
}
#[inline]
pub const fn pow(self, n: i8) -> Self {
Self {
l: self.l * n,
m: self.m * n,
t: self.t * n,
i: self.i * n,
th: self.th * n,
n: self.n * n,
j: self.j * n,
}
}
pub fn name(&self) -> &'static str {
if *self == Self::DIMENSIONLESS {
return "Dimensionless";
}
if *self == Self::LENGTH {
return "Length";
}
if *self == Self::MASS {
return "Mass";
}
if *self == Self::TIME {
return "Time";
}
if *self == Self::CURRENT {
return "Current";
}
if *self == Self::TEMPERATURE {
return "Temperature";
}
if *self == Self::AREA {
return "Area";
}
if *self == Self::VOLUME {
return "Volume";
}
if *self == Self::VELOCITY {
return "Velocity";
}
if *self == Self::ACCELERATION {
return "Acceleration";
}
if *self == Self::FREQUENCY {
return "Frequency";
}
if *self == Self::ANGULAR_ACCELERATION {
return "AngularAcceleration";
}
if *self == Self::FORCE {
return "Force";
}
if *self == Self::ENERGY {
return "Energy";
}
if *self == Self::POWER {
return "Power";
}
if *self == Self::MOMENTUM {
return "Momentum";
}
if *self == Self::ANGULAR_MOMENTUM {
return "AngularMomentum";
}
if *self == Self::MOMENT_OF_INERTIA {
return "MomentOfInertia";
}
if *self == Self::PRESSURE {
return "Pressure";
}
if *self == Self::STIFFNESS {
return "Stiffness";
}
if *self == Self::DAMPING {
return "Damping";
}
if *self == Self::VOLTAGE {
return "Voltage";
}
if *self == Self::RESISTANCE {
return "Resistance";
}
if *self == Self::INDUCTANCE {
return "Inductance";
}
if *self == Self::CAPACITANCE {
return "Capacitance";
}
if *self == Self::CHARGE {
return "Charge";
}
if *self == Self::MAGNETIC_FLUX {
return "MagneticFlux";
}
"Unknown"
}
pub fn from_name(name: &str) -> Option<ConstDim> {
match name {
"Dimensionless" => Some(Self::DIMENSIONLESS),
"Angle" => Some(Self::ANGLE),
"Length" => Some(Self::LENGTH),
"Mass" => Some(Self::MASS),
"Time" => Some(Self::TIME),
"Current" => Some(Self::CURRENT),
"Temperature" => Some(Self::TEMPERATURE),
"Area" => Some(Self::AREA),
"Volume" => Some(Self::VOLUME),
"Velocity" => Some(Self::VELOCITY),
"Acceleration" => Some(Self::ACCELERATION),
"AngularVelocity" => Some(Self::ANGULAR_VELOCITY),
"AngularAcceleration" => Some(Self::ANGULAR_ACCELERATION),
"Frequency" => Some(Self::FREQUENCY),
"Force" => Some(Self::FORCE),
"Energy" => Some(Self::ENERGY),
"Torque" => Some(Self::TORQUE),
"Power" => Some(Self::POWER),
"Momentum" => Some(Self::MOMENTUM),
"AngularMomentum" => Some(Self::ANGULAR_MOMENTUM),
"MomentOfInertia" => Some(Self::MOMENT_OF_INERTIA),
"Pressure" => Some(Self::PRESSURE),
"Stiffness" => Some(Self::STIFFNESS),
"Damping" => Some(Self::DAMPING),
"Voltage" => Some(Self::VOLTAGE),
"Resistance" => Some(Self::RESISTANCE),
"Inductance" => Some(Self::INDUCTANCE),
"Capacitance" => Some(Self::CAPACITANCE),
"Charge" => Some(Self::CHARGE),
"MagneticFlux" => Some(Self::MAGNETIC_FLUX),
_ => None,
}
}
}
impl ConstDim {
pub const DIMENSIONLESS: Self = Self::new(0, 0, 0, 0, 0, 0, 0);
pub const ANGLE: Self = Self::new(0, 0, 0, 0, 0, 0, 0);
pub const LENGTH: Self = Self::new(1, 0, 0, 0, 0, 0, 0);
pub const MASS: Self = Self::new(0, 1, 0, 0, 0, 0, 0);
pub const TIME: Self = Self::new(0, 0, 1, 0, 0, 0, 0);
pub const CURRENT: Self = Self::new(0, 0, 0, 1, 0, 0, 0);
pub const TEMPERATURE: Self = Self::new(0, 0, 0, 0, 1, 0, 0);
pub const AREA: Self = Self::new(2, 0, 0, 0, 0, 0, 0);
pub const VOLUME: Self = Self::new(3, 0, 0, 0, 0, 0, 0);
pub const VELOCITY: Self = Self::new(1, 0, -1, 0, 0, 0, 0);
pub const ACCELERATION: Self = Self::new(1, 0, -2, 0, 0, 0, 0);
pub const ANGULAR_VELOCITY: Self = Self::new(0, 0, -1, 0, 0, 0, 0);
pub const ANGULAR_ACCELERATION: Self = Self::new(0, 0, -2, 0, 0, 0, 0);
pub const FREQUENCY: Self = Self::new(0, 0, -1, 0, 0, 0, 0);
pub const FORCE: Self = Self::new(1, 1, -2, 0, 0, 0, 0);
pub const ENERGY: Self = Self::new(2, 1, -2, 0, 0, 0, 0);
pub const TORQUE: Self = Self::new(2, 1, -2, 0, 0, 0, 0);
pub const POWER: Self = Self::new(2, 1, -3, 0, 0, 0, 0);
pub const MOMENTUM: Self = Self::new(1, 1, -1, 0, 0, 0, 0);
pub const ANGULAR_MOMENTUM: Self = Self::new(2, 1, -1, 0, 0, 0, 0);
pub const MOMENT_OF_INERTIA: Self = Self::new(2, 1, 0, 0, 0, 0, 0);
pub const PRESSURE: Self = Self::new(-1, 1, -2, 0, 0, 0, 0);
pub const STIFFNESS: Self = Self::new(0, 1, -2, 0, 0, 0, 0);
pub const DAMPING: Self = Self::new(0, 1, -1, 0, 0, 0, 0);
pub const VOLTAGE: Self = Self::new(2, 1, -3, -1, 0, 0, 0);
pub const RESISTANCE: Self = Self::new(2, 1, -3, -2, 0, 0, 0);
pub const INDUCTANCE: Self = Self::new(2, 1, -2, -2, 0, 0, 0);
pub const CAPACITANCE: Self = Self::new(-2, -1, 4, 2, 0, 0, 0);
pub const CHARGE: Self = Self::new(0, 0, 1, 1, 0, 0, 0);
pub const MAGNETIC_FLUX: Self = Self::new(2, 1, -2, -1, 0, 0, 0);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn const_dim_mul_div_roundtrip() {
let force = ConstDim::MASS.mul(ConstDim::ACCELERATION);
assert!(force.eq(ConstDim::FORCE));
let mass_back = ConstDim::FORCE.div(ConstDim::ACCELERATION);
assert!(mass_back.eq(ConstDim::MASS));
}
#[test]
fn const_dim_energy_from_force_times_length() {
let energy = ConstDim::FORCE.mul(ConstDim::LENGTH);
assert!(energy.eq(ConstDim::ENERGY));
}
#[test]
fn const_dim_power_from_energy_div_time() {
let power = ConstDim::ENERGY.div(ConstDim::TIME);
assert!(power.eq(ConstDim::POWER));
}
#[test]
fn const_dim_ohms_law() {
let voltage = ConstDim::CURRENT.mul(ConstDim::RESISTANCE);
assert!(voltage.eq(ConstDim::VOLTAGE));
}
#[test]
fn const_dim_charge_from_current_times_time() {
let charge = ConstDim::CURRENT.mul(ConstDim::TIME);
assert!(charge.eq(ConstDim::CHARGE));
}
#[test]
fn dim_name_force() {
assert_eq!(ForceDim::dim_name(), "Force");
assert_eq!(ForceDim::dim_symbol(), "N");
}
#[test]
fn dim_name_voltage() {
assert_eq!(VoltageDim::dim_name(), "Voltage");
assert_eq!(VoltageDim::dim_symbol(), "V");
}
const _: () = {
let f = ConstDim::MASS.mul(ConstDim::ACCELERATION);
assert!(f.eq(ConstDim::FORCE));
};
}