use std::fmt;
use std::marker::PhantomData;
use typenum::consts::*;
use typenum::{Diff, Integer, NonZero, PartialDiv, Sum};
use crate::ops::*;
use crate::quantity::*;
use crate::ratio::*;
use crate::typenum_ext::*;
pub use self::ratios::*;
pub trait SIUnits {
type Ratios: SIRatios;
type Exponents: SIExponents;
}
pub trait SIRatios {
type Length: Ratio;
type Mass: Ratio;
type Time: Ratio;
}
pub trait SIExponents {
type Length: Integer;
type Mass: Integer;
type Time: Integer;
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct SIUnitsT<RATIOS, EXPONENTS>
where
RATIOS: SIRatios,
EXPONENTS: SIExponents,
{
_r: PhantomData<RATIOS>,
_e: PhantomData<EXPONENTS>,
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct SIRatiosT<L, M, T>
where
L: Ratio,
M: Ratio,
T: Ratio,
{
_l: PhantomData<L>,
_m: PhantomData<M>,
_t: PhantomData<T>,
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct SIExponentsT<L, M, T>
where
L: Integer,
M: Integer,
T: Integer,
{
_l: PhantomData<L>,
_m: PhantomData<M>,
_t: PhantomData<T>,
}
#[doc(hidden)]
#[derive(Default)]
pub struct RatioExponentT<R: Ratio, E: Integer> {
_r: PhantomData<R>,
_e: PhantomData<E>,
}
#[doc(hidden)]
#[derive(Copy, Clone)]
pub struct AmountT<T: Amount>(T);
impl<R, E> Invert for SIUnitsT<R, E>
where
R: SIRatios,
E: SIExponents,
units::Dimensionless: std::ops::Div<Self>,
DivOutput<units::Dimensionless, Self>: Default,
{
type Output = DivOutput<units::Dimensionless, Self>;
fn invert(self) -> Self::Output {
Default::default()
}
}
impl<R, E> std::ops::Add<SIUnitsT<R, E>> for SIUnitsT<R, E>
where
R: SIRatios,
E: SIExponents,
{
type Output = Self;
fn add(self, _other: Self) -> Self::Output {
SIUnitsT {
_r: PhantomData,
_e: PhantomData,
}
}
}
impl<R, E> std::ops::Sub<SIUnitsT<R, E>> for SIUnitsT<R, E>
where
R: SIRatios,
E: SIExponents,
{
type Output = Self;
fn sub(self, _other: Self) -> Self::Output {
SIUnitsT {
_r: PhantomData,
_e: PhantomData,
}
}
}
impl<L0, M0, T0, L1, M1, T1> std::ops::Add<SIExponentsT<L1, M1, T1>> for SIExponentsT<L0, M0, T0>
where
L0: Integer + std::ops::Add<L1>,
M0: Integer + std::ops::Add<M1>,
T0: Integer + std::ops::Add<T1>,
L1: Integer,
M1: Integer,
T1: Integer,
AddOutput<L0, L1>: Integer,
AddOutput<M0, M1>: Integer,
AddOutput<T0, T1>: Integer,
{
type Output = SIExponentsT<Sum<L0, L1>, Sum<M0, M1>, Sum<T0, T1>>;
fn add(self, _other: SIExponentsT<L1, M1, T1>) -> Self::Output {
SIExponentsT {
_l: PhantomData,
_m: PhantomData,
_t: PhantomData,
}
}
}
impl<L0, M0, T0, L1, M1, T1> std::ops::Sub<SIExponentsT<L1, M1, T1>> for SIExponentsT<L0, M0, T0>
where
L0: Integer + std::ops::Sub<L1>,
M0: Integer + std::ops::Sub<M1>,
T0: Integer + std::ops::Sub<T1>,
L1: Integer,
M1: Integer,
T1: Integer,
SubOutput<L0, L1>: Integer,
SubOutput<M0, M1>: Integer,
SubOutput<T0, T1>: Integer,
{
type Output = SIExponentsT<Diff<L0, L1>, Diff<M0, M1>, Diff<T0, T1>>;
fn sub(self, _other: SIExponentsT<L1, M1, T1>) -> Self::Output {
SIExponentsT {
_l: PhantomData,
_m: PhantomData,
_t: PhantomData,
}
}
}
impl<R0, E0, R1, E1> std::ops::Mul<SIUnitsT<R1, E1>> for SIUnitsT<R0, E0>
where
R0: SIRatios + Xor<R1>,
E0: SIExponents + std::ops::Add<E1>,
R1: SIRatios,
E1: SIExponents,
XorOutput<R0, R1>: SIRatios + ReduceWith<AddOutput<E0, E1>> + Default,
AddOutput<E0, E1>: SIExponents + Default,
ReduceWithOutput<XorOutput<R0, R1>, AddOutput<E0, E1>>: SIRatios + Default,
ReduceOutput<SIUnitsT<XorOutput<R0, R1>, AddOutput<E0, E1>>>: Default,
{
type Output = ReduceOutput<SIUnitsT<XorOutput<R0, R1>, AddOutput<E0, E1>>>;
fn mul(self, _other: SIUnitsT<R1, E1>) -> Self::Output {
Default::default()
}
}
impl<R0, E0, R1, E1> std::ops::Div<SIUnitsT<R1, E1>> for SIUnitsT<R0, E0>
where
R0: SIRatios + Xor<R1>,
E0: SIExponents + std::ops::Sub<E1>,
R1: SIRatios,
E1: SIExponents,
XorOutput<R0, R1>: SIRatios + ReduceWith<SubOutput<E0, E1>> + Default,
SubOutput<E0, E1>: SIExponents + Default,
ReduceWithOutput<XorOutput<R0, R1>, SubOutput<E0, E1>>: SIRatios + Default,
ReduceOutput<SIUnitsT<XorOutput<R0, R1>, SubOutput<E0, E1>>>: Default,
{
type Output = ReduceOutput<SIUnitsT<XorOutput<R0, R1>, SubOutput<E0, E1>>>;
fn div(self, _other: SIUnitsT<R1, E1>) -> Self::Output {
Default::default()
}
}
impl<L, M, T> SIRatios for SIRatiosT<L, M, T>
where
L: Ratio,
M: Ratio,
T: Ratio,
{
type Length = L;
type Mass = M;
type Time = T;
}
impl<L, M, T> SIExponents for SIExponentsT<L, M, T>
where
L: Integer,
M: Integer,
T: Integer,
{
type Length = L;
type Mass = M;
type Time = T;
}
impl<R, E> SIUnits for SIUnitsT<R, E>
where
R: SIRatios,
E: SIExponents,
{
type Ratios = R;
type Exponents = E;
}
impl<L0, M0, T0, L1, M1, T1> Xor<SIRatiosT<L1, M1, T1>> for SIRatiosT<L0, M0, T0>
where
L0: Ratio + Xor<L1>,
M0: Ratio + Xor<M1>,
T0: Ratio + Xor<T1>,
L1: Ratio,
M1: Ratio,
T1: Ratio,
XorOutput<L0, L1>: Ratio + Default,
XorOutput<M0, M1>: Ratio + Default,
XorOutput<T0, T1>: Ratio + Default,
{
type Output = SIRatiosT<XorOutput<L0, L1>, XorOutput<M0, M1>, XorOutput<T0, T1>>;
fn xor(self, _other: SIRatiosT<L1, M1, T1>) -> Self::Output {
Default::default()
}
}
impl<L0, M0, T0, L1, M1, T1> Xor<SIExponentsT<L1, M1, T1>> for SIExponentsT<L0, M0, T0>
where
L0: Integer + Xor<L1>,
M0: Integer + Xor<M1>,
T0: Integer + Xor<T1>,
L1: Integer,
M1: Integer,
T1: Integer,
XorOutput<L0, L1>: Integer + Default,
XorOutput<M0, M1>: Integer + Default,
XorOutput<T0, T1>: Integer + Default,
{
type Output = SIExponentsT<XorOutput<L0, L1>, XorOutput<M0, M1>, XorOutput<T0, T1>>;
fn xor(self, _other: SIExponentsT<L1, M1, T1>) -> Self::Output {
Default::default()
}
}
impl<R0, E0, R1, E1> Xor<SIUnitsT<R1, E1>> for SIUnitsT<R0, E0>
where
R0: SIRatios + Xor<R1>,
E0: SIExponents + Xor<E1>,
R1: SIRatios,
E1: SIExponents,
XorOutput<R0, R1>: SIRatios,
XorOutput<E0, E1>: SIExponents,
SIUnitsT<XorOutput<R0, R1>, XorOutput<E0, E1>>: Default,
{
type Output = SIUnitsT<XorOutput<R0, R1>, XorOutput<E0, E1>>;
fn xor(self, _other: SIUnitsT<R1, E1>) -> Self::Output {
Default::default()
}
}
impl<L, M, T, E> ReduceWith<E> for SIRatiosT<L, M, T>
where
L: Ratio + ReduceWith<E::Length>,
M: Ratio + ReduceWith<E::Mass>,
T: Ratio + ReduceWith<E::Time>,
E: SIExponents,
ReduceWithOutput<L, E::Length>: Ratio + Default,
ReduceWithOutput<M, E::Mass>: Ratio + Default,
ReduceWithOutput<T, E::Time>: Ratio + Default,
{
type Output = SIRatiosT<
ReduceWithOutput<L, E::Length>,
ReduceWithOutput<M, E::Mass>,
ReduceWithOutput<T, E::Time>,
>;
fn reduce_with(self, _other: E) -> Self::Output {
Default::default()
}
}
impl<R, E> Reduce for SIUnitsT<R, E>
where
R: SIRatios + ReduceWith<E>,
E: SIExponents,
ReduceWithOutput<R, E>: SIRatios,
SIUnitsT<ReduceWithOutput<R, E>, E>: Default,
{
type Output = SIUnitsT<ReduceWithOutput<R, E>, E>;
fn reduce(self) -> Self::Output {
Default::default()
}
}
impl<T, R, E> std::ops::Mul<SIUnitsT<R, E>> for AmountT<T>
where
T: Amount,
AmountT<T>: std::ops::Mul<RatioExponentT<R::Length, E::Length>, Output = Self>
+ std::ops::Mul<RatioExponentT<R::Mass, E::Mass>, Output = Self>
+ std::ops::Mul<RatioExponentT<R::Time, E::Time>, Output = Self>,
R: SIRatios,
E: SIExponents,
{
type Output = Self;
fn mul(self, _other: SIUnitsT<R, E>) -> Self::Output {
let mut result = self;
result = result
* RatioExponentT::<R::Length, E::Length> {
_r: PhantomData,
_e: PhantomData,
};
result = result
* RatioExponentT::<R::Mass, E::Mass> {
_r: PhantomData,
_e: PhantomData,
};
result = result
* RatioExponentT::<R::Time, E::Time> {
_r: PhantomData,
_e: PhantomData,
};
result
}
}
impl<T, R, E> std::ops::Div<SIUnitsT<R, E>> for AmountT<T>
where
T: Amount,
AmountT<T>: std::ops::Div<RatioExponentT<R::Length, E::Length>, Output = Self>
+ std::ops::Div<RatioExponentT<R::Mass, E::Mass>, Output = Self>
+ std::ops::Div<RatioExponentT<R::Time, E::Time>, Output = Self>,
R: SIRatios,
E: SIExponents,
{
type Output = Self;
fn div(self, _other: SIUnitsT<R, E>) -> Self::Output {
let mut result = self;
result = result
/ RatioExponentT::<R::Length, E::Length> {
_r: PhantomData,
_e: PhantomData,
};
result = result
/ RatioExponentT::<R::Mass, E::Mass> {
_r: PhantomData,
_e: PhantomData,
};
result = result
/ RatioExponentT::<R::Time, E::Time> {
_r: PhantomData,
_e: PhantomData,
};
result
}
}
impl<T, R1, R2, E> ConvertUnits<QuantityT<T, SIUnitsT<R1, E>>> for QuantityT<T, SIUnitsT<R2, E>>
where
T: Amount,
AmountT<T>: std::ops::Mul<SIUnitsT<R1, E>, Output = AmountT<T>>
+ std::ops::Div<SIUnitsT<R1, E>, Output = AmountT<T>>
+ std::ops::Mul<SIUnitsT<R2, E>, Output = AmountT<T>>
+ std::ops::Div<SIUnitsT<R2, E>, Output = AmountT<T>>,
R1: SIRatios,
R2: SIRatios,
E: SIExponents,
{
fn convert_from(other: QuantityT<T, SIUnitsT<R1, E>>) -> Self {
let amount = AmountT(other.amount());
let r1: SIUnitsT<R1, E> = SIUnitsT {
_r: PhantomData,
_e: PhantomData,
};
let r2: SIUnitsT<R2, E> = SIUnitsT {
_r: PhantomData,
_e: PhantomData,
};
let result = amount / r2 * r1;
Self::new(result.0)
}
fn convert_into(self) -> QuantityT<T, SIUnitsT<R1, E>> {
QuantityT::<T, SIUnitsT<R1, E>>::convert_from(self)
}
}
impl<T1, T2, U> CastAmount<QuantityT<T2, U>> for QuantityT<T1, U>
where
T1: Amount + num_traits::NumCast,
T2: Amount + num_traits::NumCast,
{
fn cast_from(other: QuantityT<T2, U>) -> Self {
Self::new(num_traits::cast(other.amount()).unwrap())
}
fn cast_into(self) -> QuantityT<T2, U> {
QuantityT::<T2, U>::new(num_traits::cast(self.amount()).unwrap())
}
}
impl<R, E> std::fmt::Display for SIUnitsT<R, E>
where
R: SIRatios,
E: SIExponents,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut any = false;
let e = E::Length::to_i64();
if e != 0 {
assert!(R::Length::numerator() != 0 && R::Length::denominator() != 0);
any = true;
write_ratio_symbol_short::<R::Length>(f)?;
write!(f, "m")?;
if e != 1 {
write_superscript(e, f)?;
}
};
let e = E::Mass::to_i64();
if e != 0 {
assert!(R::Mass::numerator() != 0 && R::Mass::denominator() != 0);
if any {
write!(f, "·")?;
}
any = true;
write_ratio_symbol_short::<R::Mass>(f)?;
write!(f, "g")?;
if e != 1 {
write_superscript(e, f)?;
}
};
let e = E::Time::to_i64();
if e != 0 {
assert!(R::Time::numerator() != 0 && R::Time::denominator() != 0);
if any {
write!(f, "·")?;
}
write_ratio_symbol_time_short::<R::Time>(f)?;
if e != 1 {
write_superscript(e, f)?;
}
};
Ok(())
}
}
fn write_superscript(num: i64, f: &mut fmt::Formatter) -> fmt::Result {
const NEG: &char = &'⁻';
const DIGITS: &[char; 10] = &[
'⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹',
];
let mut digits: [u8; 48] = [0; 48];
let mut num_digits = 0;
let mut num = num;
if num < 0 {
write!(f, "{}", NEG)?;
num = num.abs();
}
while num != 0 {
let digit = num % 10;
num /= 10;
digits[num_digits] = digit as u8;
num_digits += 1;
}
let slice = &digits[0..num_digits];
for digit in slice.iter().rev() {
let idx = *digit as usize;
write!(f, "{}", DIGITS[idx])?;
}
Ok(())
}
fn write_ratio_symbol_short<R: Ratio>(f: &mut fmt::Formatter) -> fmt::Result {
let n = R::numerator();
let d = R::denominator();
match (n, d) {
(1_000_000_000_000_000, 1) => write!(f, "P"),
(1_000_000_000_000, 1) => write!(f, "T"),
(1_000_000_000, 1) => write!(f, "G"),
(1_000_000, 1) => write!(f, "M"),
(1_000, 1) => write!(f, "k"),
(100, 1) => write!(f, "h"),
(10, 1) => write!(f, "da"),
(1, 1) => Ok(()),
(1, 10) => write!(f, "d"),
(1, 100) => write!(f, "c"),
(1, 1_000) => write!(f, "m"),
(1, 1_000_000) => write!(f, "μ"),
(1, 1_000_000_000) => write!(f, "n"),
(1, 1_000_000_000_000) => write!(f, "p"),
(1, 1_000_000_000_000_000) => write!(f, "f"),
(_, _) => write!(f, "({}/{})", n, d),
}
}
fn write_ratio_symbol_time_short<R: Ratio>(f: &mut fmt::Formatter) -> fmt::Result {
let n = R::numerator();
let d = R::denominator();
match (n, d) {
(3_600, 1) => write!(f, "h"),
(60, 1) => write!(f, "m"),
(1, 1) => write!(f, "s"),
(1, 10) => write!(f, "ds"),
(1, 100) => write!(f, "cs"),
(1, 1_000) => write!(f, "ms"),
(1, 1_000_000) => write!(f, "μs"),
(1, 1_000_000_000) => write!(f, "ns"),
(1, 1_000_000_000_000) => write!(f, "ps"),
(1, 1_000_000_000_000_000) => write!(f, "fs"),
(_, _) => write!(f, "({}/{})", n, d),
}
}
impl<R, E> Sqrt for SIUnitsT<R, E>
where
R: SIRatios,
E: SIExponents,
E::Length: PartialDiv<P2>,
E::Mass: PartialDiv<P2>,
E::Time: PartialDiv<P2>,
<E::Length as PartialDiv<P2>>::Output: Integer,
<E::Mass as PartialDiv<P2>>::Output: Integer,
<E::Time as PartialDiv<P2>>::Output: Integer,
SIUnitsT<
R,
SIExponentsT<
<E::Length as PartialDiv<P2>>::Output,
<E::Mass as PartialDiv<P2>>::Output,
<E::Time as PartialDiv<P2>>::Output,
>,
>: Default,
{
type Output = SIUnitsT<
R,
SIExponentsT<
<E::Length as PartialDiv<P2>>::Output,
<E::Mass as PartialDiv<P2>>::Output,
<E::Time as PartialDiv<P2>>::Output,
>,
>;
fn sqrt(self) -> Self::Output {
Default::default()
}
}
impl<T, R, U> std::ops::Mul<RatioExponentT<R, typenum::PInt<U>>> for AmountT<T>
where
T: Amount + std::ops::Mul<T> + num_traits::NumCast,
R: Ratio,
U: typenum::Unsigned + NonZero,
MulOutput<T, T>: std::ops::Div<T, Output = T>,
{
type Output = AmountT<T>;
fn mul(self, _other: RatioExponentT<R, typenum::PInt<U>>) -> Self::Output {
let amount = self.0;
let n: T = num_traits::cast(R::numerator()).unwrap();
let d: T = num_traits::cast(R::denominator()).unwrap();
let result = amount * n / d;
AmountT(result)
}
}
impl<T, R, U> std::ops::Div<RatioExponentT<R, typenum::PInt<U>>> for AmountT<T>
where
T: Amount + std::ops::Mul<T> + num_traits::NumCast,
R: Ratio,
U: typenum::Unsigned + NonZero,
MulOutput<T, T>: std::ops::Div<T, Output = T>,
{
type Output = AmountT<T>;
fn div(self, _other: RatioExponentT<R, typenum::PInt<U>>) -> Self::Output {
let amount = self.0;
let n: T = num_traits::cast(R::numerator()).unwrap();
let d: T = num_traits::cast(R::denominator()).unwrap();
let result = amount * d / n;
AmountT(result)
}
}
impl<T, R, U> std::ops::Mul<RatioExponentT<R, typenum::NInt<U>>> for AmountT<T>
where
T: Amount + std::ops::Mul<T> + num_traits::NumCast,
R: Ratio,
U: typenum::Unsigned + NonZero,
MulOutput<T, T>: std::ops::Div<T, Output = T>,
{
type Output = AmountT<T>;
fn mul(self, _other: RatioExponentT<R, typenum::NInt<U>>) -> Self::Output {
let amount = self.0;
let n: T = num_traits::cast(R::numerator()).unwrap();
let d: T = num_traits::cast(R::denominator()).unwrap();
let result = amount * d / n;
AmountT(result)
}
}
impl<T, R, U> std::ops::Div<RatioExponentT<R, typenum::NInt<U>>> for AmountT<T>
where
T: Amount + std::ops::Mul<T> + num_traits::NumCast,
R: Ratio,
U: typenum::Unsigned + NonZero,
MulOutput<T, T>: std::ops::Div<T, Output = T>,
{
type Output = AmountT<T>;
fn div(self, _other: RatioExponentT<R, typenum::NInt<U>>) -> Self::Output {
let amount = self.0;
let n: T = num_traits::cast(R::numerator()).unwrap();
let d: T = num_traits::cast(R::denominator()).unwrap();
let result = amount * n / d;
AmountT(result)
}
}
impl<T> std::ops::Mul<RatioExponentT<RatioZero, typenum::Z0>> for AmountT<T>
where
T: Amount,
{
type Output = AmountT<T>;
fn mul(self, _other: RatioExponentT<RatioZero, typenum::Z0>) -> AmountT<T> {
self
}
}
impl<T> std::ops::Div<RatioExponentT<RatioZero, typenum::Z0>> for AmountT<T>
where
T: Amount,
{
type Output = AmountT<T>;
fn div(self, _other: RatioExponentT<RatioZero, typenum::Z0>) -> AmountT<T> {
self
}
}
pub mod ratios {
use super::*;
use typenum::Exp;
pub type Peta = RatioT<Exp<P10, P15>, P1>;
pub type Tera = RatioT<Exp<P10, P12>, P1>;
pub type Giga = RatioT<Exp<P10, P9>, P1>;
pub type Mega = RatioT<Exp<P10, P6>, P1>;
pub type Kilo = RatioT<Exp<P10, P3>, P1>;
pub type Hecto = RatioT<Exp<P10, P2>, P1>;
pub type Deca = RatioT<Exp<P10, P1>, P1>;
pub type Zero = RatioZero;
pub type Unit = RatioT<P1, P1>;
pub type Deci = RatioT<P1, Exp<P10, P1>>;
pub type Centi = RatioT<P1, Exp<P10, P2>>;
pub type Milli = RatioT<P1, Exp<P10, P3>>;
pub type Micro = RatioT<P1, Exp<P10, P6>>;
pub type Nano = RatioT<P1, Exp<P10, P9>>;
pub type Pico = RatioT<P1, Exp<P10, P12>>;
pub type Femto = RatioT<P1, Exp<P10, P15>>;
pub type Second = Unit;
pub type Minute = RatioT<P60, P1>;
pub type Hour = RatioT<P3600, P1>;
pub type Day = RatioT<P86400, P1>;
pub type Year = RatioT<P31536000, P1>;
pub type Length<R> = SIRatiosT<R, Zero, Zero>;
pub type Mass<R> = SIRatiosT<Zero, R, Zero>;
pub type Time<R> = SIRatiosT<Zero, Zero, R>;
}
pub mod exponents {
use super::*;
pub type Length = SIExponentsT<P1, Z0, Z0>;
pub type Mass = SIExponentsT<Z0, P1, Z0>;
pub type Time = SIExponentsT<Z0, Z0, P1>;
}
pub mod units {
use super::*;
pub type Dimensionless = SIUnitsT<SIRatiosT<Zero, Zero, Zero>, SIExponentsT<Z0, Z0, Z0>>;
pub type Length<R> = SIUnitsT<ratios::Length<R>, exponents::Length>;
pub type Mass<R> = SIUnitsT<ratios::Mass<R>, exponents::Mass>;
pub type Time<R> = SIUnitsT<ratios::Time<R>, exponents::Time>;
}
pub mod quantities {
use super::*;
pub type Dimensionless<T> =
QuantityT<T, SIUnitsT<SIRatiosT<Zero, Zero, Zero>, SIExponentsT<Z0, Z0, Z0>>>;
pub type Length<T, R> = QuantityT<T, units::Length<R>>;
pub type Mass<T, R> = QuantityT<T, units::Mass<R>>;
pub type Time<T, R> = QuantityT<T, units::Time<R>>;
pub type Area<T, R> =
QuantityT<T, SIUnitsT<SIRatiosT<R, Zero, Zero>, SIExponentsT<P2, Z0, Z0>>>;
pub type Velocity<T, RL, RT> =
QuantityT<T, SIUnitsT<SIRatiosT<RL, Zero, RT>, SIExponentsT<P1, Z0, N1>>>;
pub type Acceleration<T, RL, RT> =
QuantityT<T, SIUnitsT<SIRatiosT<RL, Zero, RT>, SIExponentsT<P1, Z0, N2>>>;
pub type Petameters<T> = Length<T, Peta>;
pub type Terameters<T> = Length<T, Tera>;
pub type Gigameters<T> = Length<T, Giga>;
pub type Megameters<T> = Length<T, Mega>;
pub type Kilometers<T> = Length<T, Kilo>;
pub type Hectometers<T> = Length<T, Hecto>;
pub type Decameters<T> = Length<T, Deca>;
pub type Zerometers<T> = Length<T, Zero>;
pub type Meters<T> = Length<T, Unit>;
pub type Decimeters<T> = Length<T, Deci>;
pub type Centimeters<T> = Length<T, Centi>;
pub type Millimeters<T> = Length<T, Milli>;
pub type Micrometers<T> = Length<T, Micro>;
pub type Nanometers<T> = Length<T, Nano>;
pub type Picometers<T> = Length<T, Pico>;
pub type Femtometers<T> = Length<T, Femto>;
pub type Petagrams<T> = Mass<T, Peta>;
pub type Teragrams<T> = Mass<T, Tera>;
pub type Gigagrams<T> = Mass<T, Giga>;
pub type Megagrams<T> = Mass<T, Mega>;
pub type Kilograms<T> = Mass<T, Kilo>;
pub type Hectograms<T> = Mass<T, Hecto>;
pub type Decagrams<T> = Mass<T, Deca>;
pub type Zerograms<T> = Mass<T, Zero>;
pub type Grams<T> = Mass<T, Unit>;
pub type Decigrams<T> = Mass<T, Deci>;
pub type Centigrams<T> = Mass<T, Centi>;
pub type Milligrams<T> = Mass<T, Milli>;
pub type Micrograms<T> = Mass<T, Micro>;
pub type Nanograms<T> = Mass<T, Nano>;
pub type Picograms<T> = Mass<T, Pico>;
pub type Femtograms<T> = Mass<T, Femto>;
pub type Years<T> = Time<T, Year>;
pub type Days<T> = Time<T, Day>;
pub type Hours<T> = Time<T, Hour>;
pub type Minutes<T> = Time<T, Minute>;
pub type Seconds<T> = Time<T, Unit>;
pub type Milliseconds<T> = Time<T, Milli>;
pub type Microseconds<T> = Time<T, Micro>;
pub type Nanoseconds<T> = Time<T, Nano>;
pub type Picoseconds<T> = Time<T, Pico>;
pub type Femtoseconds<T> = Time<T, Femto>;
pub type MetersPerSecond<T> = Velocity<T, Unit, Unit>;
pub type MetersPerSecond2<T> = Acceleration<T, Unit, Unit>;
pub type KilometersPerHour<T> = Velocity<T, Kilo, Hour>;
pub mod f32 {
use super::*;
pub type Dimensionless =
QuantityT<f32, SIUnitsT<SIRatiosT<Zero, Zero, Zero>, SIExponentsT<Z0, Z0, Z0>>>;
pub type Length<R> = QuantityT<f32, units::Length<R>>;
pub type Mass<R> = QuantityT<f32, units::Mass<R>>;
pub type Time<R> = QuantityT<f32, units::Time<R>>;
pub type Petameters = Length<Peta>;
pub type Terameters = Length<Tera>;
pub type Gigameters = Length<Giga>;
pub type Megameters = Length<Mega>;
pub type Kilometers = Length<Kilo>;
pub type Hectometers = Length<Hecto>;
pub type Decameters = Length<Deca>;
pub type Zerometers = Length<Zero>;
pub type Meters = Length<Unit>;
pub type Decimeters = Length<Deci>;
pub type Centimeters = Length<Centi>;
pub type Millimeters = Length<Milli>;
pub type Micrometers = Length<Micro>;
pub type Nanometers = Length<Nano>;
pub type Picometers = Length<Pico>;
pub type Femtometers = Length<Femto>;
pub type Kilograms = Mass<Kilo>;
pub type Grams = Mass<Unit>;
pub type Years = Time<Year>;
pub type Days = Time<Day>;
pub type Hours = Time<Hour>;
pub type Minutes = Time<Minute>;
pub type Seconds = Time<Unit>;
pub type Milliseconds = Time<Milli>;
pub type Microseconds = Time<Micro>;
pub type Nanoseconds = Time<Nano>;
pub type Picoseconds = Time<Pico>;
pub type Femtoseconds = Time<Femto>;
pub type MetersPerSecond = super::MetersPerSecond<f32>;
pub type MetersPerSecond2 = super::MetersPerSecond2<f32>;
pub type KilometersPerHour = super::KilometersPerHour<f32>;
}
pub mod traits {
use crate::quantity::{Amount, ConvertUnits, Quantity};
use crate::ratio::Ratio;
pub trait Length: Quantity + Copy {
fn convert<R>(self) -> super::Length<Self::AmountType, R>
where
R: Ratio,
Self::AmountType: Amount;
}
pub trait Time: Quantity + Copy {
fn convert<R>(self) -> super::Time<Self::AmountType, R>
where
R: Ratio,
Self::AmountType: Amount;
}
pub trait Area: Quantity {
fn convert<R>(self) -> super::Area<Self::AmountType, R>
where
R: Ratio,
Self::AmountType: Amount;
}
pub trait Velocity: Quantity {
fn convert<RL, RT>(self) -> super::Velocity<Self::AmountType, RL, RT>
where
RL: Ratio,
RT: Ratio,
Self::AmountType: Amount;
}
pub trait Acceleration: Quantity {
fn convert<RL, RT>(self) -> super::Acceleration<Self::AmountType, RL, RT>
where
RL: Ratio,
RT: Ratio,
Self::AmountType: Amount;
}
impl<T, R> Length for super::Length<T, R>
where
T: Amount
+ num_traits::NumCast
+ std::ops::Mul<T, Output = T>
+ std::ops::Div<T, Output = T>,
R: Ratio + Copy,
{
fn convert<R2>(self) -> super::Length<Self::AmountType, R2>
where
R2: Ratio,
Self: super::ConvertUnits<super::Length<Self::AmountType, R2>>,
{
self.convert_into()
}
}
impl<T, R> Time for super::Time<T, R>
where
T: Amount
+ num_traits::NumCast
+ std::ops::Mul<T, Output = T>
+ std::ops::Div<T, Output = T>,
R: Ratio + Copy,
{
fn convert<R2>(self) -> super::Time<Self::AmountType, R2>
where
R2: Ratio,
Self: super::ConvertUnits<super::Time<Self::AmountType, R2>>,
{
self.convert_into()
}
}
impl<T, R> Area for super::Area<T, R>
where
T: Amount
+ num_traits::NumCast
+ std::ops::Mul<T, Output = T>
+ std::ops::Div<T, Output = T>,
R: Ratio + Copy,
{
fn convert<R2>(self) -> super::Area<Self::AmountType, R2>
where
R2: Ratio,
Self: super::ConvertUnits<super::Area<Self::AmountType, R2>>,
{
self.convert_into()
}
}
impl<T, RL, RT> Velocity for super::Velocity<T, RL, RT>
where
T: Amount
+ num_traits::NumCast
+ std::ops::Mul<T, Output = T>
+ std::ops::Div<T, Output = T>,
RL: Ratio + Copy,
RT: Ratio + Copy,
{
fn convert<RL2, RT2>(self) -> super::Velocity<Self::AmountType, RL2, RT2>
where
RL2: Ratio,
RT2: Ratio,
Self: super::ConvertUnits<super::Velocity<Self::AmountType, RL2, RT2>>,
{
self.convert_into()
}
}
impl<T, RL, RT> Acceleration for super::Acceleration<T, RL, RT>
where
T: Amount
+ num_traits::NumCast
+ std::ops::Mul<T, Output = T>
+ std::ops::Div<T, Output = T>,
RL: Ratio + Copy,
RT: Ratio + Copy,
{
fn convert<RL2, RT2>(self) -> super::Acceleration<Self::AmountType, RL2, RT2>
where
RL2: Ratio,
RT2: Ratio,
Self: super::ConvertUnits<super::Acceleration<Self::AmountType, RL2, RT2>>,
{
self.convert_into()
}
}
}
}