1106 lines
34 KiB
Rust
1106 lines
34 KiB
Rust
use std::{
|
|
fmt::{Display, Formatter},
|
|
marker::PhantomData,
|
|
ops::{
|
|
Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub,
|
|
SubAssign,
|
|
},
|
|
};
|
|
|
|
use num_traits::{Num, One, Zero};
|
|
use typenum::{int::Z0, op, Integer};
|
|
|
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
|
pub struct SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
{
|
|
value: T,
|
|
_s: PhantomData<Second>,
|
|
_m: PhantomData<Meter>,
|
|
_kg: PhantomData<Kilogram>,
|
|
_a: PhantomData<Ampere>,
|
|
_k: PhantomData<Kelvin>,
|
|
_mol: PhantomData<Mole>,
|
|
_cd: PhantomData<Candela>,
|
|
}
|
|
|
|
macro_rules! display_unit_defmt {
|
|
($formatter: ident, $param: ident, $symbol: literal, $e1: ident, $e2: ident, $e3: ident, $e4: ident, $e5: ident, $e6: ident) => {
|
|
if $param::I64 != 0 {
|
|
if $e1::I64 == 0
|
|
&& $e2::I64 == 0
|
|
&& $e3::I64 == 0
|
|
&& $e4::I64 == 0
|
|
&& $e5::I64 == 0
|
|
&& $e6::I64 == 0
|
|
{
|
|
defmt::write!($formatter, $symbol);
|
|
} else {
|
|
defmt::write!($formatter, "*{}", $symbol);
|
|
}
|
|
if $param::I64 != 1 {
|
|
defmt::write!($formatter, "^{}", $param::I64);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! display_special_unit_defmt {
|
|
($formatter: ident, $self: ident, $(($symbol: literal, $other: ty)),* $(,)?) => {
|
|
$(
|
|
if ::core::any::TypeId::of::<$self>() == ::core::any::TypeId::of::<$other>() {
|
|
defmt::write!($formatter, $symbol);
|
|
return;
|
|
}
|
|
)*
|
|
};
|
|
}
|
|
|
|
#[cfg(feature = "defmt")]
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> defmt::Format
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: defmt::Format + 'static,
|
|
{
|
|
fn format(&self, f: defmt::Formatter<'_>) {
|
|
defmt::write!(f, "{}", self.value);
|
|
// derived units with special symbols
|
|
display_special_unit_defmt!(f, Self,
|
|
("Hz", Herz<T>),
|
|
("N", Newton<T>),
|
|
("Pa", Pascal<T>),
|
|
("J", Joule<T>),
|
|
("W", Watt<T>),
|
|
("C", Coulomb<T>),
|
|
("V", Volt<T>),
|
|
("F", Farad<T>),
|
|
("Ohm", Ohm<T>),
|
|
("S", Siemens<T>),
|
|
("Wb", Weber<T>),
|
|
("T", Tesla<T>),
|
|
("H", Henry<T>),
|
|
("lx", Lux<T>),
|
|
("Gy|Sv", Gray<T>),
|
|
("kat", Katal<T>),
|
|
);
|
|
// derived units
|
|
display_special_unit_defmt!(f, Self,
|
|
("m/s", MeterPerSecond<T>),
|
|
("m/s²", MeterPerSquareSecond<T>),
|
|
("kg/m³", KilogramPerCubicMeter<T>),
|
|
("kg/m²", KilogramPerSquareMeter<T>),
|
|
("m³/kg", KilogramPerSquareMeter<T>),
|
|
("A/m²", AmperePerSquareMeter<T>),
|
|
("A/m", AmperePerMeter<T>),
|
|
("mol/m³", MolePerCubicMeter<T>),
|
|
("cd/m²", CandelaPerSquareMeter<T>),
|
|
);
|
|
// derived units including special names
|
|
display_special_unit_defmt!(f, Self,
|
|
("Pa*s", PascalSecond<T>),
|
|
("N*m", NewtonMeter<T>),
|
|
("N/m", NewtonPerMeter<T>),
|
|
("W/m²", WattPerSquareMeter<T>),
|
|
("J/K", JoulePerKelvin<T>),
|
|
("J/(kg*K)", JoulePerKilogramKelvin<T>),
|
|
("J/kg", JoulePerKilogram<T>),
|
|
("W/(m*K)", WattPerMeterKelvin<T>),
|
|
("J/m³", JoulePerCubicMeter<T>),
|
|
("V/m", VoltPerMeter<T>),
|
|
("C/m³", CoulombPerCubicMeter<T>),
|
|
("C/m²", CoulombPerSquareMeter<T>),
|
|
("F/m", FaradPerMeter<T>),
|
|
("H/m", HenryPerMeter<T>),
|
|
("J/mol", JoulePerMole<T>),
|
|
("J/(mol*K)", JoulePerMoleKelvin<T>),
|
|
("C/kg", CoulombPerKilogram<T>),
|
|
("Gy/s", GrayPerSecond<T>),
|
|
("kat/m³", KatalPerCubicMeter<T>),
|
|
);
|
|
|
|
// base units
|
|
display_unit_defmt!(f, Second, "s", Meter, Kilogram, Ampere, Kelvin, Mole, Candela);
|
|
display_unit_defmt!(f, Meter, "m", Second, Kilogram, Ampere, Kelvin, Mole, Candela);
|
|
display_unit_defmt!(f, Kilogram, "kg", Second, Meter, Ampere, Kelvin, Mole, Candela);
|
|
display_unit_defmt!(f, Ampere, "A", Second, Meter, Kilogram, Kelvin, Mole, Candela);
|
|
display_unit_defmt!(f, Kelvin, "K", Second, Meter, Kilogram, Ampere, Mole, Candela);
|
|
display_unit_defmt!(f, Mole, "mol", Second, Meter, Kilogram, Ampere, Kelvin, Candela);
|
|
display_unit_defmt!(f, Candela, "cd", Second, Meter, Kilogram, Ampere, Kelvin, Mole);
|
|
}
|
|
}
|
|
|
|
macro_rules! display_unit {
|
|
($formatter: ident, $param: ident, $symbol: literal, $e1: ident, $e2: ident, $e3: ident, $e4: ident, $e5: ident, $e6: ident) => {
|
|
if $param::I64 != 0 {
|
|
if $e1::I64 == 0
|
|
&& $e2::I64 == 0
|
|
&& $e3::I64 == 0
|
|
&& $e4::I64 == 0
|
|
&& $e5::I64 == 0
|
|
&& $e6::I64 == 0
|
|
{
|
|
write!($formatter, $symbol)?;
|
|
} else {
|
|
write!($formatter, "*{}", $symbol)?;
|
|
}
|
|
if $param::I64 != 1 {
|
|
write!($formatter, "^{}", $param::I64)?;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! display_special_unit {
|
|
($formatter: ident, $self: ident, $(($symbol: literal, $other: ty)),* $(,)?) => {
|
|
$(
|
|
if ::core::any::TypeId::of::<$self>() == ::core::any::TypeId::of::<$other>() {
|
|
return write!($formatter, $symbol);
|
|
}
|
|
)*
|
|
};
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> Display
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: Display + 'static,
|
|
{
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", self.value)?;
|
|
// derived units with special symbols
|
|
display_special_unit!(f, Self,
|
|
("Hz", Herz<T>),
|
|
("N", Newton<T>),
|
|
("Pa", Pascal<T>),
|
|
("J", Joule<T>),
|
|
("W", Watt<T>),
|
|
("C", Coulomb<T>),
|
|
("V", Volt<T>),
|
|
("F", Farad<T>),
|
|
("Ohm", Ohm<T>),
|
|
("S", Siemens<T>),
|
|
("Wb", Weber<T>),
|
|
("T", Tesla<T>),
|
|
("H", Henry<T>),
|
|
("lx", Lux<T>),
|
|
("Gy|Sv", Gray<T>),
|
|
("kat", Katal<T>),
|
|
);
|
|
// derived units
|
|
display_special_unit!(f, Self,
|
|
("m/s", MeterPerSecond<T>),
|
|
("m/s²", MeterPerSquareSecond<T>),
|
|
("kg/m³", KilogramPerCubicMeter<T>),
|
|
("kg/m²", KilogramPerSquareMeter<T>),
|
|
("m³/kg", KilogramPerSquareMeter<T>),
|
|
("A/m²", AmperePerSquareMeter<T>),
|
|
("A/m", AmperePerMeter<T>),
|
|
("mol/m³", MolePerCubicMeter<T>),
|
|
("cd/m²", CandelaPerSquareMeter<T>),
|
|
);
|
|
// derived units including special names
|
|
display_special_unit!(f, Self,
|
|
("Pa*s", PascalSecond<T>),
|
|
("N*m", NewtonMeter<T>),
|
|
("N/m", NewtonPerMeter<T>),
|
|
("W/m²", WattPerSquareMeter<T>),
|
|
("J/K", JoulePerKelvin<T>),
|
|
("J/(kg*K)", JoulePerKilogramKelvin<T>),
|
|
("J/kg", JoulePerKilogram<T>),
|
|
("W/(m*K)", WattPerMeterKelvin<T>),
|
|
("J/m³", JoulePerCubicMeter<T>),
|
|
("V/m", VoltPerMeter<T>),
|
|
("C/m³", CoulombPerCubicMeter<T>),
|
|
("C/m²", CoulombPerSquareMeter<T>),
|
|
("F/m", FaradPerMeter<T>),
|
|
("H/m", HenryPerMeter<T>),
|
|
("J/mol", JoulePerMole<T>),
|
|
("J/(mol*K)", JoulePerMoleKelvin<T>),
|
|
("C/kg", CoulombPerKilogram<T>),
|
|
("Gy/s", GrayPerSecond<T>),
|
|
("kat/m³", KatalPerCubicMeter<T>),
|
|
);
|
|
|
|
// base units
|
|
display_unit!(f, Second, "s", Meter, Kilogram, Ampere, Kelvin, Mole, Candela);
|
|
display_unit!(f, Meter, "m", Second, Kilogram, Ampere, Kelvin, Mole, Candela);
|
|
display_unit!(f, Kilogram, "kg", Second, Meter, Ampere, Kelvin, Mole, Candela);
|
|
display_unit!(f, Ampere, "A", Second, Meter, Kilogram, Kelvin, Mole, Candela);
|
|
display_unit!(f, Kelvin, "K", Second, Meter, Kilogram, Ampere, Mole, Candela);
|
|
display_unit!(f, Mole, "mol", Second, Meter, Kilogram, Ampere, Kelvin, Candela);
|
|
display_unit!(f, Candela, "cd", Second, Meter, Kilogram, Ampere, Kelvin, Mole);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> Deref
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
{
|
|
type Target = T;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.value
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> DerefMut
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
{
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.value
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> Neg
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: Neg,
|
|
{
|
|
type Output = SiUnit<T::Output, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>;
|
|
|
|
fn neg(self) -> Self::Output {
|
|
Self::Output::new(-self.value)
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> Zero
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: Zero,
|
|
{
|
|
fn zero() -> Self {
|
|
Self::new(T::zero())
|
|
}
|
|
|
|
fn is_zero(&self) -> bool {
|
|
self.value.is_zero()
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> One
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer + Add<Output = Second>,
|
|
Meter: Integer + Add<Output = Meter>,
|
|
Kilogram: Integer + Add<Output = Kilogram>,
|
|
Ampere: Integer + Add<Output = Ampere>,
|
|
Kelvin: Integer + Add<Output = Kelvin>,
|
|
Mole: Integer + Add<Output = Mole>,
|
|
Candela: Integer + Add<Output = Candela>,
|
|
T: One,
|
|
<Second as Add>::Output: Integer,
|
|
<Meter as Add>::Output: Integer,
|
|
<Kilogram as Add>::Output: Integer,
|
|
<Ampere as Add>::Output: Integer,
|
|
<Kelvin as Add>::Output: Integer,
|
|
<Mole as Add>::Output: Integer,
|
|
<Candela as Add>::Output: Integer,
|
|
{
|
|
fn one() -> Self {
|
|
Self::new(T::one())
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> Num
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer + Add<Output = Second> + Sub<Output = Second> + PartialEq,
|
|
Meter: Integer + Add<Output = Meter> + Sub<Output = Meter> + PartialEq,
|
|
Kilogram: Integer + Add<Output = Kilogram> + Sub<Output = Kilogram> + PartialEq,
|
|
Ampere: Integer + Add<Output = Ampere> + Sub<Output = Ampere> + PartialEq,
|
|
Kelvin: Integer + Add<Output = Kelvin> + Sub<Output = Kelvin> + PartialEq,
|
|
Mole: Integer + Add<Output = Mole> + Sub<Output = Mole> + PartialEq,
|
|
Candela: Integer + Add<Output = Candela> + Sub<Output = Candela> + PartialEq,
|
|
T: Num,
|
|
{
|
|
type FromStrRadixErr = T::FromStrRadixErr;
|
|
|
|
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
|
|
T::from_str_radix(str, radix).map(Self::new)
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> Add
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: Add,
|
|
{
|
|
type Output = SiUnit<T::Output, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>;
|
|
|
|
fn add(self, rhs: Self) -> Self::Output {
|
|
Self::Output::new(self.value + rhs.value)
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> AddAssign
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: AddAssign,
|
|
{
|
|
fn add_assign(&mut self, rhs: Self) {
|
|
self.value += rhs.value;
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> Sub
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: Sub,
|
|
{
|
|
type Output = SiUnit<T::Output, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>;
|
|
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
Self::Output::new(self.value - rhs.value)
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> SubAssign
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: SubAssign,
|
|
{
|
|
fn sub_assign(&mut self, rhs: Self) {
|
|
self.value -= rhs.value;
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> Mul<T>
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: Mul,
|
|
{
|
|
type Output = <Self as Mul<Unit<T>>>::Output;
|
|
|
|
fn mul(self, rhs: T) -> Self::Output {
|
|
self * Unit::new(rhs)
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> MulAssign<T>
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: MulAssign,
|
|
{
|
|
fn mul_assign(&mut self, rhs: T) {
|
|
self.value *= rhs;
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> Div<T>
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer + Sub<Z0>,
|
|
Meter: Integer + Sub<Z0>,
|
|
Kilogram: Integer + Sub<Z0>,
|
|
Ampere: Integer + Sub<Z0>,
|
|
Kelvin: Integer + Sub<Z0>,
|
|
Mole: Integer + Sub<Z0>,
|
|
Candela: Integer + Sub<Z0>,
|
|
T: Div,
|
|
<Second as Sub<Z0>>::Output: Integer,
|
|
<Meter as Sub<Z0>>::Output: Integer,
|
|
<Kilogram as Sub<Z0>>::Output: Integer,
|
|
<Ampere as Sub<Z0>>::Output: Integer,
|
|
<Kelvin as Sub<Z0>>::Output: Integer,
|
|
<Mole as Sub<Z0>>::Output: Integer,
|
|
<Candela as Sub<Z0>>::Output: Integer,
|
|
{
|
|
type Output = <Self as Div<Unit<T>>>::Output;
|
|
|
|
fn div(self, rhs: T) -> Self::Output {
|
|
self / Unit::new(rhs)
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> DivAssign<T>
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: DivAssign,
|
|
{
|
|
fn div_assign(&mut self, rhs: T) {
|
|
self.value /= rhs;
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> Rem<T>
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer + Sub<Z0>,
|
|
Meter: Integer + Sub<Z0>,
|
|
Kilogram: Integer + Sub<Z0>,
|
|
Ampere: Integer + Sub<Z0>,
|
|
Kelvin: Integer + Sub<Z0>,
|
|
Mole: Integer + Sub<Z0>,
|
|
Candela: Integer + Sub<Z0>,
|
|
T: Rem,
|
|
<Second as Sub<Z0>>::Output: Integer,
|
|
<Meter as Sub<Z0>>::Output: Integer,
|
|
<Kilogram as Sub<Z0>>::Output: Integer,
|
|
<Ampere as Sub<Z0>>::Output: Integer,
|
|
<Kelvin as Sub<Z0>>::Output: Integer,
|
|
<Mole as Sub<Z0>>::Output: Integer,
|
|
<Candela as Sub<Z0>>::Output: Integer,
|
|
{
|
|
type Output = <Self as Rem<Unit<T>>>::Output;
|
|
|
|
fn rem(self, rhs: T) -> Self::Output {
|
|
self % Unit::new(rhs)
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela> RemAssign<T>
|
|
for SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
T: RemAssign,
|
|
{
|
|
fn rem_assign(&mut self, rhs: T) {
|
|
self.value %= rhs;
|
|
}
|
|
}
|
|
|
|
impl<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
SiUnit<T, Second, Meter, Kilogram, Ampere, Kelvin, Mole, Candela>
|
|
where
|
|
Second: Integer,
|
|
Meter: Integer,
|
|
Kilogram: Integer,
|
|
Ampere: Integer,
|
|
Kelvin: Integer,
|
|
Mole: Integer,
|
|
Candela: Integer,
|
|
{
|
|
pub const fn new(value: T) -> Self {
|
|
Self {
|
|
value,
|
|
_s: PhantomData,
|
|
_m: PhantomData,
|
|
_kg: PhantomData,
|
|
_a: PhantomData,
|
|
_k: PhantomData,
|
|
_mol: PhantomData,
|
|
_cd: PhantomData,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<
|
|
T,
|
|
Second1,
|
|
Meter1,
|
|
Kilogram1,
|
|
Ampere1,
|
|
Kelvin1,
|
|
Mole1,
|
|
Candela1,
|
|
Second2,
|
|
Meter2,
|
|
Kilogram2,
|
|
Ampere2,
|
|
Kelvin2,
|
|
Mole2,
|
|
Candela2,
|
|
> Mul<SiUnit<T, Second1, Meter1, Kilogram1, Ampere1, Kelvin1, Mole1, Candela1>>
|
|
for SiUnit<T, Second2, Meter2, Kilogram2, Ampere2, Kelvin2, Mole2, Candela2>
|
|
where
|
|
Mole2: Integer,
|
|
Candela2: Integer,
|
|
Candela1: Integer + Add<Candela2>,
|
|
Mole1: Integer + Add<Mole2>,
|
|
Kelvin1: Integer + Add<Kelvin2>,
|
|
Ampere1: Integer + Add<Ampere2>,
|
|
Kilogram1: Integer + Add<Kilogram2>,
|
|
Meter1: Integer + Add<Meter2>,
|
|
Second1: Integer + Add<Second2>,
|
|
Kelvin2: Integer,
|
|
Ampere2: Integer,
|
|
Kilogram2: Integer,
|
|
Meter2: Integer,
|
|
Second2: Integer,
|
|
T: Mul,
|
|
Second1::Output: Integer,
|
|
Meter1::Output: Integer,
|
|
Kilogram1::Output: Integer,
|
|
Ampere1::Output: Integer,
|
|
Kelvin1::Output: Integer,
|
|
Mole1::Output: Integer,
|
|
Candela1::Output: Integer,
|
|
{
|
|
type Output = SiUnit<
|
|
T::Output,
|
|
op!(Second1 + Second2),
|
|
op!(Meter1 + Meter2),
|
|
op!(Kilogram1 + Kilogram2),
|
|
op!(Ampere1 + Ampere2),
|
|
op!(Kelvin1 + Kelvin2),
|
|
op!(Mole1 + Mole2),
|
|
op!(Candela1 + Candela2),
|
|
>;
|
|
|
|
fn mul(
|
|
self,
|
|
rhs: SiUnit<T, Second1, Meter1, Kilogram1, Ampere1, Kelvin1, Mole1, Candela1>,
|
|
) -> Self::Output {
|
|
Self::Output::new(self.value * rhs.value)
|
|
}
|
|
}
|
|
|
|
impl<
|
|
T,
|
|
Second1,
|
|
Meter1,
|
|
Kilogram1,
|
|
Ampere1,
|
|
Kelvin1,
|
|
Mole1,
|
|
Candela1,
|
|
Second2,
|
|
Meter2,
|
|
Kilogram2,
|
|
Ampere2,
|
|
Kelvin2,
|
|
Mole2,
|
|
Candela2,
|
|
> Div<SiUnit<T, Second1, Meter1, Kilogram1, Ampere1, Kelvin1, Mole1, Candela1>>
|
|
for SiUnit<T, Second2, Meter2, Kilogram2, Ampere2, Kelvin2, Mole2, Candela2>
|
|
where
|
|
Second1: Integer,
|
|
Meter1: Integer,
|
|
Kilogram1: Integer,
|
|
Ampere1: Integer,
|
|
Kelvin1: Integer,
|
|
Mole1: Integer,
|
|
Candela1: Integer,
|
|
Second2: Integer + Sub<Second1>,
|
|
Meter2: Integer + Sub<Meter1>,
|
|
Kilogram2: Integer + Sub<Kilogram1>,
|
|
Ampere2: Integer + Sub<Ampere1>,
|
|
Kelvin2: Integer + Sub<Kelvin1>,
|
|
Mole2: Integer + Sub<Mole1>,
|
|
Candela2: Integer + Sub<Candela1>,
|
|
T: Div,
|
|
Second2::Output: Integer,
|
|
Meter2::Output: Integer,
|
|
Kilogram2::Output: Integer,
|
|
Ampere2::Output: Integer,
|
|
Kelvin2::Output: Integer,
|
|
Mole2::Output: Integer,
|
|
Candela2::Output: Integer,
|
|
{
|
|
type Output = SiUnit<
|
|
T::Output,
|
|
op!(Second2 - Second1),
|
|
op!(Meter2 - Meter1),
|
|
op!(Kilogram2 - Kilogram1),
|
|
op!(Ampere2 - Ampere1),
|
|
op!(Kelvin2 - Kelvin1),
|
|
op!(Mole2 - Mole1),
|
|
op!(Candela2 - Candela1),
|
|
>;
|
|
|
|
fn div(
|
|
self,
|
|
rhs: SiUnit<T, Second1, Meter1, Kilogram1, Ampere1, Kelvin1, Mole1, Candela1>,
|
|
) -> Self::Output {
|
|
Self::Output::new(self.value / rhs.value)
|
|
}
|
|
}
|
|
|
|
impl<
|
|
T,
|
|
Second1,
|
|
Meter1,
|
|
Kilogram1,
|
|
Ampere1,
|
|
Kelvin1,
|
|
Mole1,
|
|
Candela1,
|
|
Second2,
|
|
Meter2,
|
|
Kilogram2,
|
|
Ampere2,
|
|
Kelvin2,
|
|
Mole2,
|
|
Candela2,
|
|
> Rem<SiUnit<T, Second1, Meter1, Kilogram1, Ampere1, Kelvin1, Mole1, Candela1>>
|
|
for SiUnit<T, Second2, Meter2, Kilogram2, Ampere2, Kelvin2, Mole2, Candela2>
|
|
where
|
|
Second1: Integer,
|
|
Meter1: Integer,
|
|
Kilogram1: Integer,
|
|
Ampere1: Integer,
|
|
Kelvin1: Integer,
|
|
Mole1: Integer,
|
|
Candela1: Integer,
|
|
Second2: Integer + Sub<Second1>,
|
|
Meter2: Integer + Sub<Meter1>,
|
|
Kilogram2: Integer + Sub<Kilogram1>,
|
|
Ampere2: Integer + Sub<Ampere1>,
|
|
Kelvin2: Integer + Sub<Kelvin1>,
|
|
Mole2: Integer + Sub<Mole1>,
|
|
Candela2: Integer + Sub<Candela1>,
|
|
T: Rem,
|
|
Second2::Output: Integer,
|
|
Meter2::Output: Integer,
|
|
Kilogram2::Output: Integer,
|
|
Ampere2::Output: Integer,
|
|
Kelvin2::Output: Integer,
|
|
Mole2::Output: Integer,
|
|
Candela2::Output: Integer,
|
|
{
|
|
type Output = SiUnit<
|
|
T::Output,
|
|
op!(Second2 - Second1),
|
|
op!(Meter2 - Meter1),
|
|
op!(Kilogram2 - Kilogram1),
|
|
op!(Ampere2 - Ampere1),
|
|
op!(Kelvin2 - Kelvin1),
|
|
op!(Mole2 - Mole1),
|
|
op!(Candela2 - Candela1),
|
|
>;
|
|
|
|
fn rem(
|
|
self,
|
|
rhs: SiUnit<T, Second1, Meter1, Kilogram1, Ampere1, Kelvin1, Mole1, Candela1>,
|
|
) -> Self::Output {
|
|
Self::Output::new(self.value % rhs.value)
|
|
}
|
|
}
|
|
|
|
#[rustfmt::skip]
|
|
mod aliases {
|
|
use super::SiUnit;
|
|
use typenum::consts::{N1, N2, N3, P1, P2, P3, P4, Z0};
|
|
// Base units
|
|
pub type Unit<T> = SiUnit<T, Z0, Z0, Z0, Z0, Z0, Z0, Z0>;
|
|
/// time
|
|
pub type Second<T> = SiUnit<T, P1, Z0, Z0, Z0, Z0, Z0, Z0>;
|
|
/// length
|
|
pub type Meter<T> = SiUnit<T, Z0, P1, Z0, Z0, Z0, Z0, Z0>;
|
|
/// mass
|
|
pub type Kilogram<T> = SiUnit<T, Z0, Z0, P1, Z0, Z0, Z0, Z0>;
|
|
/// electric current
|
|
pub type Ampere<T> = SiUnit<T, Z0, Z0, Z0, P1, Z0, Z0, Z0>;
|
|
/// thermodynamic temperature
|
|
pub type Kelvin<T> = SiUnit<T, Z0, Z0, Z0, Z0, P1, Z0, Z0>;
|
|
/// amount of substance
|
|
pub type Mole<T> = SiUnit<T, Z0, Z0, Z0, Z0, Z0, P1, Z0>;
|
|
/// luminous intensity
|
|
pub type Candela<T> = SiUnit<T, Z0, Z0, Z0, Z0, Z0, Z0, P1>;
|
|
|
|
// Derived units with special names
|
|
/// plane angle
|
|
pub type Radian<T> = Unit<T>;
|
|
/// solid angle
|
|
pub type Steradian<T> = Unit<T>;
|
|
/// frequency
|
|
pub type Herz<T> = SiUnit<T, N1, Z0, Z0, Z0, Z0, Z0, Z0>;
|
|
/// force, weight
|
|
pub type Newton<T> = SiUnit<T, N2, P1, P1, Z0, Z0, Z0, Z0>;
|
|
/// pressure, stress
|
|
pub type Pascal<T> = SiUnit<T, N2, N1, P1, Z0, Z0, Z0, Z0>;
|
|
/// energy, work, heat
|
|
pub type Joule<T> = SiUnit<T, N2, P2, P1, Z0, Z0, Z0, Z0>;
|
|
/// power, radiant flux
|
|
pub type Watt<T> = SiUnit<T, N3, P2, P1, Z0, Z0, Z0, Z0>;
|
|
/// electric charge
|
|
pub type Coulomb<T> = SiUnit<T, P1, Z0, Z0, P1, Z0, Z0, Z0>;
|
|
/// electric potential, voltage, emf
|
|
pub type Volt<T> = SiUnit<T, N3, P2, P1, N1, Z0, Z0, Z0>;
|
|
/// capacitance
|
|
pub type Farad<T> = SiUnit<T, P4, N2, N1, P2, Z0, Z0, Z0>;
|
|
/// resistance impedance, reactance
|
|
pub type Ohm<T> = SiUnit<T, N3, P2, P1, N2, Z0, Z0, Z0>;
|
|
/// electrical conductance
|
|
pub type Siemens<T> = SiUnit<T, P3, N2, N1, P2, Z0, Z0, Z0>;
|
|
/// magnetic flux
|
|
pub type Weber<T> = SiUnit<T, N2, P2, P1, N1, Z0, Z0, Z0>;
|
|
/// magnetic flux density
|
|
pub type Tesla<T> = SiUnit<T, N2, Z0, P1, N1, Z0, Z0, Z0>;
|
|
/// inductance
|
|
pub type Henry<T> = SiUnit<T, N2, P2, P1, N2, Z0, Z0, Z0>;
|
|
/// luminous flux
|
|
pub type Lumen<T> = Candela<T>;
|
|
/// iluminance
|
|
pub type Lux<T> = SiUnit<T, Z0, N2, Z0, Z0, Z0, Z0, P1>;
|
|
/// activity referred to a radionuclide
|
|
pub type Becquerel<T> = Herz<T>;
|
|
/// absorbed dose
|
|
pub type Gray<T> = SiUnit<T, N2, P2, Z0, Z0, Z0, Z0, Z0>;
|
|
/// equivalent dose
|
|
pub type Sievert<T> = Gray<T>;
|
|
/// catalytic activity
|
|
pub type Katal<T> = SiUnit<T, N1, Z0, Z0, Z0, Z0, P1, Z0>;
|
|
|
|
// Derived units without special names
|
|
/// area
|
|
pub type SquareMeter<T> = SiUnit<T, Z0, P2, Z0, Z0, Z0, Z0, Z0>;
|
|
/// volume
|
|
pub type CubicMeter<T> = SiUnit<T, Z0, P3, Z0, Z0, Z0, Z0, Z0>;
|
|
/// speed, velocity
|
|
pub type MeterPerSecond<T> = SiUnit<T, N1, P1, Z0, Z0, Z0, Z0, Z0>;
|
|
/// acceleration
|
|
pub type MeterPerSquareSecond<T> = SiUnit<T, N2, P1, Z0, Z0, Z0, Z0, Z0>;
|
|
/// wavenumber, vergence
|
|
pub type ReciprocalMeter<T> = SiUnit<T, Z0, N1, Z0, Z0, Z0, Z0, Z0>;
|
|
/// density, mass concentration
|
|
pub type KilogramPerCubicMeter<T> = SiUnit<T, Z0, N3, P1, Z0, Z0, Z0, Z0>;
|
|
/// surface density
|
|
pub type KilogramPerSquareMeter<T> = SiUnit<T, Z0, N2, P1, Z0, Z0, Z0, Z0>;
|
|
/// specific density
|
|
pub type CubicMeterPerKilogram<T> = SiUnit<T, Z0, P3, N1, Z0, Z0, Z0, Z0>;
|
|
/// current density
|
|
pub type AmperePerSquareMeter<T> = SiUnit<T, Z0, N2, Z0, P1, Z0, Z0, Z0>;
|
|
/// magnetic field strength
|
|
pub type AmperePerMeter<T> = SiUnit<T, Z0, N1, Z0, P1, Z0, Z0, Z0>;
|
|
/// concentration
|
|
pub type MolePerCubicMeter<T> = SiUnit<T, Z0, N3, Z0, Z0, Z0, P1, Z0>;
|
|
/// luminance
|
|
pub type CandelaPerSquareMeter<T> = SiUnit<T, Z0, N2, Z0, Z0, Z0, Z0, P1>;
|
|
|
|
// Derived units including special names
|
|
/// dynamic viscosity
|
|
pub type PascalSecond<T> = SiUnit<T, N1, N1, P1, Z0, Z0, Z0, Z0>;
|
|
/// moment of force
|
|
pub type NewtonMeter<T> = SiUnit<T, N2, P2, P1, Z0, Z0, Z0, Z0>;
|
|
/// surface tension
|
|
pub type NewtonPerMeter<T> = SiUnit<T, N2, Z0, P1, Z0, Z0, Z0, Z0>;
|
|
/// angular velocity, angular frequency
|
|
pub type RadianPerSecond<T> = SiUnit<T, N1, Z0, Z0, Z0, Z0, Z0, Z0>;
|
|
/// angular acceleration
|
|
pub type RadianPerSquareSecond<T> = SiUnit<T, N2, Z0, Z0, Z0, Z0, Z0, Z0>;
|
|
/// heat flux density, irradiance
|
|
pub type WattPerSquareMeter<T> = SiUnit<T, N3, Z0, P1, Z0, Z0, Z0, Z0>;
|
|
/// entropy, heat capacity
|
|
pub type JoulePerKelvin<T> = SiUnit<T, N2, P2, P1, Z0, N1, Z0, Z0>;
|
|
/// specific heat capacity, specific entropy
|
|
pub type JoulePerKilogramKelvin<T> = SiUnit<T, N2, P2, Z0, Z0, N1, Z0, Z0>;
|
|
/// specific energy
|
|
pub type JoulePerKilogram<T> = SiUnit<T, N2, P2, Z0, Z0, Z0, Z0, Z0>;
|
|
/// themal conductivity
|
|
pub type WattPerMeterKelvin<T> = SiUnit<T, N3, P1, P1, Z0, N1, Z0, Z0>;
|
|
/// energy density
|
|
pub type JoulePerCubicMeter<T> = SiUnit<T, N2, N1, P1, Z0, Z0, Z0, Z0>;
|
|
/// electric field strength
|
|
pub type VoltPerMeter<T> = SiUnit<T, N3, P1, P1, N1, Z0, Z0, Z0>;
|
|
/// electric charge density
|
|
pub type CoulombPerCubicMeter<T> = SiUnit<T, P1, N3, Z0, P1, Z0, Z0, Z0>;
|
|
/// surface charge density, electirc flusx density, electric displacement
|
|
pub type CoulombPerSquareMeter<T> = SiUnit<T, P1, N2, Z0, P1, Z0, Z0, Z0>;
|
|
/// permittivity
|
|
pub type FaradPerMeter<T> = SiUnit<T, P4, N3, N1, P2, Z0, Z0, Z0>;
|
|
/// permeability
|
|
pub type HenryPerMeter<T> = SiUnit<T, N2, P1, P1, N2, Z0, Z0, Z0>;
|
|
/// molar energy
|
|
pub type JoulePerMole<T> = SiUnit<T, N2, P2, P1, Z0, Z0, N1, Z0>;
|
|
/// molar entropy, molar heat capacity
|
|
pub type JoulePerMoleKelvin<T> = SiUnit<T, N2, P2, P1, Z0, N1, N1, Z0>;
|
|
/// exposure (x- and gamma-rays)
|
|
pub type CoulombPerKilogram<T> = SiUnit<T, P1, Z0, N1, P1, Z0, Z0, Z0>;
|
|
/// absorbed dose rate
|
|
pub type GrayPerSecond<T> = SiUnit<T, N3, P2, Z0, Z0, Z0, Z0, Z0>;
|
|
/// radiant intensity
|
|
pub type WattPerSteradian<T> = SiUnit<T, N3, P2, P1, Z0, Z0, Z0, Z0>;
|
|
/// radiance
|
|
pub type WattPerSquareMeterSteradian<T> = SiUnit<T, N3, Z0, P1, Z0, Z0, Z0, Z0>;
|
|
/// catalytic activity concentration
|
|
pub type KatalPerCubicMeter<T> = SiUnit<T, N1, N3, Z0, Z0, Z0, P1, Z0>;
|
|
}
|
|
pub use aliases::*;
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn debug() {
|
|
let m = Meter::new(2);
|
|
assert_eq!(format!("{m:?}"), "SiUnit { value: 2, _s: PhantomData<typenum::int::Z0>, _m: PhantomData<typenum::int::PInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>>>, _kg: PhantomData<typenum::int::Z0>, _a: PhantomData<typenum::int::Z0>, _k: PhantomData<typenum::int::Z0>, _mol: PhantomData<typenum::int::Z0>, _cd: PhantomData<typenum::int::Z0> }".to_owned());
|
|
}
|
|
|
|
#[test]
|
|
fn display() {
|
|
let unit = Unit::new(2);
|
|
let second = Second::new(2);
|
|
let meter = Meter::new(2);
|
|
let kilogram = Kilogram::new(2);
|
|
let ampere = Ampere::new(2);
|
|
let kelvin = Kelvin::new(2);
|
|
let mole = Mole::new(2);
|
|
let candela = Candela::new(2);
|
|
assert_eq!(unit.to_string(), "2");
|
|
assert_eq!(second.to_string(), "2s");
|
|
assert_eq!(meter.to_string(), "2m");
|
|
assert_eq!(kilogram.to_string(), "2kg");
|
|
assert_eq!(ampere.to_string(), "2A");
|
|
assert_eq!(kelvin.to_string(), "2K");
|
|
assert_eq!(mole.to_string(), "2mol");
|
|
assert_eq!(candela.to_string(), "2cd");
|
|
let square_second: SiUnit<i32, _, _, _, _, _, _, _> = second * second;
|
|
let square_meter: SiUnit<i32, _, _, _, _, _, _, _> = meter * meter;
|
|
let square_kilogram: SiUnit<i32, _, _, _, _, _, _, _> = kilogram * kilogram;
|
|
let square_ampere: SiUnit<i32, _, _, _, _, _, _, _> = ampere * ampere;
|
|
let square_kelvin: SiUnit<i32, _, _, _, _, _, _, _> = kelvin * kelvin;
|
|
let square_mole: SiUnit<i32, _, _, _, _, _, _, _> = mole * mole;
|
|
let square_candela: SiUnit<i32, _, _, _, _, _, _, _> = candela * candela;
|
|
assert_eq!(square_second.to_string(), "4s^2");
|
|
assert_eq!(square_meter.to_string(), "4m^2");
|
|
assert_eq!(square_kilogram.to_string(), "4kg^2");
|
|
assert_eq!(square_ampere.to_string(), "4A^2");
|
|
assert_eq!(square_kelvin.to_string(), "4K^2");
|
|
assert_eq!(square_mole.to_string(), "4mol^2");
|
|
assert_eq!(square_candela.to_string(), "4cd^2");
|
|
let w = Watt::new(2);
|
|
assert_eq!(w.to_string(), "2W");
|
|
}
|
|
|
|
#[test]
|
|
fn clone() {
|
|
let m = Meter::new(2);
|
|
assert_eq!(m.clone(), m);
|
|
}
|
|
|
|
#[test]
|
|
fn ord() {
|
|
let a = Meter::new(2);
|
|
let b = Meter::new(3);
|
|
assert!(a < b);
|
|
assert!(b > a);
|
|
assert!(a == a);
|
|
assert!(a != b);
|
|
assert_eq!(a.max(b), b);
|
|
assert_eq!(a.min(b), a);
|
|
}
|
|
|
|
#[test]
|
|
fn deref() {
|
|
let m = Meter::new(2);
|
|
assert_eq!(*m, 2);
|
|
}
|
|
|
|
#[test]
|
|
fn deref_mut() {
|
|
let mut m = Meter::new(2);
|
|
*m = 3;
|
|
assert_eq!(*m, 3);
|
|
}
|
|
|
|
#[test]
|
|
fn neg() {
|
|
let m = Meter::new(2);
|
|
assert_eq!(-m, Meter::new(-2));
|
|
}
|
|
|
|
#[test]
|
|
fn zero() {
|
|
let z = Meter::zero();
|
|
assert_eq!(z, Meter::new(0));
|
|
assert!(z.is_zero());
|
|
}
|
|
|
|
#[test]
|
|
fn one() {
|
|
let o = Unit::one();
|
|
assert_eq!(o, Unit::new(1));
|
|
}
|
|
|
|
#[test]
|
|
fn from_str_radix() {
|
|
assert_eq!(Unit::from_str_radix("24", 10), Ok(Unit::new(24)));
|
|
}
|
|
|
|
#[test]
|
|
fn add() {
|
|
let m = Meter::new(2);
|
|
assert_eq!(m + m, Meter::new(4));
|
|
assert_eq!(m + m + m, Meter::new(6));
|
|
}
|
|
|
|
#[test]
|
|
fn add_assign() {
|
|
let mut m = Meter::new(2);
|
|
m += m;
|
|
assert_eq!(m, Meter::new(4));
|
|
}
|
|
|
|
#[test]
|
|
fn sub() {
|
|
let m = Meter::new(2);
|
|
assert_eq!(m - m, Meter::new(0));
|
|
assert_eq!(m - m - m, Meter::new(-2));
|
|
}
|
|
|
|
#[test]
|
|
fn sub_assign() {
|
|
let mut m = Meter::new(2);
|
|
m -= m;
|
|
assert_eq!(m, Meter::new(0));
|
|
}
|
|
|
|
#[test]
|
|
fn mul() {
|
|
let m = Meter::new(2);
|
|
assert_eq!(m * m, SquareMeter::new(4));
|
|
assert_eq!(m * m * m, CubicMeter::new(8));
|
|
let s = Second::new(1);
|
|
let a = Ampere::new(2);
|
|
assert_eq!(s * a, Coulomb::new(2));
|
|
let v = Volt::new(2);
|
|
assert_eq!(v * a, Watt::new(4));
|
|
assert_eq!(m * 2, Meter::new(4));
|
|
}
|
|
|
|
#[test]
|
|
fn mul_assign() {
|
|
let mut m = Meter::new(2);
|
|
m *= 2;
|
|
assert_eq!(m, Meter::new(4));
|
|
}
|
|
|
|
#[test]
|
|
fn div() {
|
|
let m = Meter::new(2);
|
|
assert_eq!(m / m, Unit::new(1));
|
|
assert_eq!(m / m / m, ReciprocalMeter::new(0));
|
|
let c = Coulomb::new(4);
|
|
let a = Ampere::new(2);
|
|
assert_eq!(c / a, Second::new(2));
|
|
let w = Watt::new(2);
|
|
assert_eq!(w / a, Volt::new(1));
|
|
assert_eq!(m / 2, Meter::new(1));
|
|
}
|
|
|
|
#[test]
|
|
fn div_assign() {
|
|
let mut m = Meter::new(2);
|
|
m /= 2;
|
|
assert_eq!(m, Meter::new(1));
|
|
}
|
|
|
|
#[test]
|
|
fn rem() {
|
|
let m = Meter::new(2);
|
|
assert_eq!(m % m, Unit::new(0));
|
|
assert_eq!(m / m % m, ReciprocalMeter::new(1));
|
|
let c = Coulomb::new(4);
|
|
let a = Ampere::new(2);
|
|
assert_eq!(c % a, Second::new(0));
|
|
let w = Watt::new(2);
|
|
assert_eq!(w % a, Volt::new(0));
|
|
assert_eq!(m % 2, Meter::new(0));
|
|
}
|
|
|
|
#[test]
|
|
fn rem_assign() {
|
|
let mut m = Meter::new(2);
|
|
m %= 2;
|
|
assert_eq!(m, Meter::new(0));
|
|
}
|
|
}
|