macro_rules! make_units { ($System:ident, $allowed_root:ident; base { $($Type:ident, $constant:ident, $print_as:ident;)* } derived {$($Derived:ident($derived_constant: ident) = $e: expr; )*} ) => (
#[derive(Copy, Clone)]
pub struct $System<$($Type: Peano),*> {
$($constant: PhantomData<$Type>),*
}
impl<$($Type: Peano),*> Dimension for $System<$($Type),*> {}
#[allow(non_camel_case_types)]
impl<$($Type),*, $($constant),*> KeepDim<$System<$($constant),*>> for $System<$($Type),*> where
$($Type: Peano + KeepPeano<$constant>),*, $($constant: Peano),* {
type Output = $System<$(<$Type as KeepPeano<$constant>>::Output),*>;
}
#[allow(non_camel_case_types)]
impl<$($Type),*, $($constant),*> AddDim<$System<$($constant),*>> for $System<$($Type),*> where
$($Type: Peano + AddPeano<$constant>),*, $($constant: Peano),* {
type Output = $System<$(<$Type as AddPeano<$constant>>::Output),*>;
}
#[allow(non_camel_case_types)]
impl<$($Type),*, $($constant),*> SubDim<$System<$($constant),*>> for $System<$($Type),*> where
$($Type: Peano + SubPeano<$constant>),*, $($constant: Peano),* {
type Output = $System<$(<$Type as SubPeano<$constant>>::Output),*>;
}
impl<$($Type),*, RHS> MulDim<RHS> for $System<$($Type),*> where
$($Type: Peano + MulPeano<RHS>),*, RHS: Peano {
type Output = $System<$(<$Type as MulPeano<RHS>>::Output),*>;
}
impl<$($Type),*, RHS> DivDim<RHS> for $System<$($Type),*> where
$($Type: Peano + DivPeano<RHS>),*, RHS: Peano {
type Output = $System<$(<$Type as DivPeano<RHS>>::Output),*>;
}
impl<$($Type),*> NegDim for $System<$($Type),*> where
$($Type: Peano + Negate),* {
type Output = $System<$(<$Type as Negate>::Output),*>;
}
impl<$($Type),*> DimToString for $System<$($Type),*>
where $($Type: ToInt),* {
fn to_string() -> String {
let mut _string = String::new();
$(
let temp = match <$Type as ToInt>::to_int() {
0 => ("", "".to_string()),
1 => (stringify!($print_as), "*".to_string()),
_power => (stringify!($print_as), format!("^{}*", _power/<$allowed_root as ToInt>::to_int()))
};
_string = format!("{}{}{}", _string, temp.0, temp.1);
)*
_string.pop();
_string
}
}
__make_types!($System, $allowed_root | $($Type),* | $($Type),* |);
#[allow(non_upper_case_globals)]
pub const one: Dim<Unitless, f64> = Dim(1.0, PhantomData);
$(#[allow(non_upper_case_globals)] pub const $constant: Dim<$Type, f64> = Dim(1.0, PhantomData);)*
);
}