#[derive(Copy,Clone,PartialEq,PartialOrd)]
pub struct Quantity<E1:NumType<E1>, E2:NumType<E2>, E3:NumType<E3>> {
amount: f64,
p1: std::marker::PhantomData<E1>,
p2: std::marker::PhantomData<E2>,
p3: std::marker::PhantomData<E3>,
}
impl<E1:NumType<E1>, E2:NumType<E2>, E3:NumType<E3>> Quantity<E1,E2,E3> {
fn new(amount: f64)-> Quantity<E1,E2,E3> {
Quantity::<E1,E2,E3> {
amount: amount,
p1: std::marker::PhantomData::<_>,
p2: std::marker::PhantomData::<_>,
p3: std::marker::PhantomData::<_>
}
}
pub fn sqrt<RE1:NumType<RE1>,RE2:NumType<RE2>,RE3:NumType<RE3>>(self) -> Quantity<RE1,RE2,RE3>
where E1:THalve<E1,Out=RE1>, E2:THalve<E2,Out=RE2>, E3:THalve<E3,Out=RE3> {
Quantity::new(self.amount.sqrt())
}
}
impl Into<f64> for Quantity<Zero,Zero,Zero> {
fn into(self) -> f64 { self.amount }
}
impl std::ops::Deref for Quantity<Zero,Zero,Zero> {
type Target = f64;
fn deref(&self) -> &Self::Target { &self.amount }
}
impl<E1:NumType<E1>, E2:NumType<E2>, E3:NumType<E3>> std::fmt::Debug for Quantity<E1,E2,E3> {
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
try!(self.amount.fmt(formatter));
let mut num: i32;
num = E1::new().into();
if num != 0 {
try!(write!(formatter, " m^{}", num));
}
num = E2::new().into();
if num != 0 {
try!(write!(formatter, " kg^{}", num));
}
num = E3::new().into();
if num != 0 {
try!(write!(formatter, " s^{}", num));
}
Ok(())
}
}
impl<E1:NumType<E1>, E2:NumType<E2>, E3:NumType<E3>> std::ops::Add for Quantity<E1,E2,E3> {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Quantity::new(self.amount + rhs.amount)
}
}
impl<E1:NumType<E1>, E2:NumType<E2>, E3:NumType<E3>> std::ops::Sub for Quantity<E1,E2,E3> {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Quantity::new(self.amount - rhs.amount)
}
}
impl<E1:NumType<E1>, E2:NumType<E2>, E3:NumType<E3>,
RE1:NumType<RE1>, RE2:NumType<RE2>, RE3:NumType<RE3>,
Out1:NumType<Out1>, Out2:NumType<Out2>, Out3:NumType<Out3>>
std::ops::Mul<Quantity<RE1,RE2,RE3>> for Quantity<E1,E2,E3>
where E1:TAdd<E1,RE1,Out=Out1>, E2:TAdd<E2,RE2,Out=Out2>, E3:TAdd<E3,RE3,Out=Out3> {
type Output = Quantity<Out1,Out2,Out3>;
fn mul(self, rhs: Quantity<RE1,RE2,RE3>) -> Self::Output {
Quantity::new(self.amount * rhs.amount)
}
}
impl<E1:NumType<E1>, E2:NumType<E2>, E3:NumType<E3>,
RE1:NumType<RE1>, RE2:NumType<RE2>, RE3:NumType<RE3>,
Out1:NumType<Out1>, Out2:NumType<Out2>, Out3:NumType<Out3>>
std::ops::Div<Quantity<RE1,RE2,RE3>> for Quantity<E1,E2,E3>
where E1:TSub<E1,RE1,Out=Out1>, E2:TSub<E2,RE2,Out=Out2>, E3:TSub<E3,RE3,Out=Out3> {
type Output = Quantity<Out1,Out2,Out3>;
fn div(self, rhs: Quantity<RE1,RE2,RE3>) -> Self::Output {
Quantity::new(self.amount / rhs.amount)
}
}
impl<E1:NumType<E1>, E2:NumType<E2>, E3:NumType<E3>> std::ops::FnOnce<(f64,)> for Quantity<E1,E2,E3> {
type Output = Quantity<E1,E2,E3>;
extern "rust-call" fn call_once(self, args: (f64,)) -> Self::Output {
Quantity::new(self.amount * args.0)
}
}
pub type One = Quantity<Zero, Zero, Zero>;
pub type Length = Quantity<P1, Zero, Zero>;
pub type Mass = Quantity<Zero, P1, Zero>;
pub type Time = Quantity<Zero, Zero, P1>;
pub const one: One = One {
amount: 1.0,
p1: std::marker::PhantomData::<_>,
p2: std::marker::PhantomData::<_>,
p3: std::marker::PhantomData::<_>
};
pub const m: Length = Quantity::<_,_,_> {
amount: 1.0,
p1: std::marker::PhantomData::<_>,
p2: std::marker::PhantomData::<_>,
p3: std::marker::PhantomData::<_>
};
pub const kg: Mass = Mass {
amount: 1.0,
p1: std::marker::PhantomData::<_>,
p2: std::marker::PhantomData::<_>,
p3: std::marker::PhantomData::<_>
};
pub const s: Time = Time {
amount: 1.0,
p1: std::marker::PhantomData::<_>,
p2: std::marker::PhantomData::<_>,
p3: std::marker::PhantomData::<_>
};