summaryrefslogtreecommitdiffstats
path: root/src/metric
diff options
context:
space:
mode:
Diffstat (limited to 'src/metric')
-rw-r--r--src/metric/absorbed_dose.rs10
-rw-r--r--src/metric/acceleration.rs10
-rw-r--r--src/metric/amount_of_substance.rs10
-rw-r--r--src/metric/area.rs28
-rw-r--r--src/metric/capacitance.rs10
-rw-r--r--src/metric/catalytic_activity.rs10
-rw-r--r--src/metric/conductance.rs39
-rw-r--r--src/metric/dose_equivalent.rs30
-rw-r--r--src/metric/electric_charge.rs10
-rw-r--r--src/metric/electric_current.rs10
-rw-r--r--src/metric/electric_potential.rs10
-rw-r--r--src/metric/electric_resistance.rs10
-rw-r--r--src/metric/energy.rs32
-rw-r--r--src/metric/force.rs10
-rw-r--r--src/metric/frequency.rs59
-rw-r--r--src/metric/illuminance.rs10
-rw-r--r--src/metric/inductance.rs10
-rw-r--r--src/metric/length.rs44
-rw-r--r--src/metric/luminous_flux.rs10
-rw-r--r--src/metric/luminous_intensity.rs10
-rw-r--r--src/metric/magnetic_flux.rs10
-rw-r--r--src/metric/magnetic_flux_density.rs10
-rw-r--r--src/metric/mass.rs36
-rw-r--r--src/metric/plane_angle.rs28
-rw-r--r--src/metric/power.rs10
-rw-r--r--src/metric/pressure.rs28
-rw-r--r--src/metric/solid_angle.rs10
-rw-r--r--src/metric/temperature.rs89
-rw-r--r--src/metric/time.rs36
-rw-r--r--src/metric/velocity.rs10
-rw-r--r--src/metric/volume.rs32
31 files changed, 671 insertions, 0 deletions
diff --git a/src/metric/absorbed_dose.rs b/src/metric/absorbed_dose.rs
new file mode 100644
index 0000000..41ef508
--- /dev/null
+++ b/src/metric/absorbed_dose.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(AbsorbedDose, Gray, "Gy"); \ No newline at end of file
diff --git a/src/metric/acceleration.rs b/src/metric/acceleration.rs
new file mode 100644
index 0000000..3b3d50a
--- /dev/null
+++ b/src/metric/acceleration.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(Acceleration, Accel, "m/s²"); \ No newline at end of file
diff --git a/src/metric/amount_of_substance.rs b/src/metric/amount_of_substance.rs
new file mode 100644
index 0000000..34058c7
--- /dev/null
+++ b/src/metric/amount_of_substance.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(AmountOfSubstance, Mole, "mol"); \ No newline at end of file
diff --git a/src/metric/area.rs b/src/metric/area.rs
new file mode 100644
index 0000000..eb2b0c3
--- /dev/null
+++ b/src/metric/area.rs
@@ -0,0 +1,28 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+pub enum Area {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ SquareMeter(f64),
+ SquareMetre(f64),
+}
+
+impl Unit<Area> for Area {
+ fn to_si_unit(&self) -> Area {
+ match self {
+ Area::Base(_, _, _) => self.clone(),
+ Area::Canonical(value) => Area::Base(value.clone(), |x| x, "m²"),
+ Area::SquareMeter(value) => Area::Base(value.clone(), |x| x, "m²"),
+ Area::SquareMetre(value) => Area::Base(value.clone(), |x| x, "m²"),
+ }
+ }
+}
+
+declare_unit_basics!(Area); \ No newline at end of file
diff --git a/src/metric/capacitance.rs b/src/metric/capacitance.rs
new file mode 100644
index 0000000..a98c203
--- /dev/null
+++ b/src/metric/capacitance.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(Capacitance, Farad, "F"); \ No newline at end of file
diff --git a/src/metric/catalytic_activity.rs b/src/metric/catalytic_activity.rs
new file mode 100644
index 0000000..710a87a
--- /dev/null
+++ b/src/metric/catalytic_activity.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(CatalyticActivity, Katal, "kat"); \ No newline at end of file
diff --git a/src/metric/conductance.rs b/src/metric/conductance.rs
new file mode 100644
index 0000000..29712e0
--- /dev/null
+++ b/src/metric/conductance.rs
@@ -0,0 +1,39 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+use crate::metric::electric_resistance::ElectricResistance;
+
+declare_simple_unit!(Conductance, Siemens, "S");
+
+// 1/s = Hz
+impl Div<ElectricResistance> for f64 {
+ type Output = Conductance;
+
+ fn div(self, rhs: ElectricResistance) -> Self::Output {
+ Conductance::Canonical(self * rhs.to_si_primitive())
+ }
+}
+
+// Hz * s = 1
+impl Mul<ElectricResistance> for Conductance {
+ type Output = f64;
+
+ fn mul(self, rhs: ElectricResistance) -> Self::Output {
+ self.to_si_primitive() * rhs.to_si_primitive()
+ }
+}
+
+// s * Hz = 1
+impl Mul<Conductance> for ElectricResistance {
+ type Output = f64;
+
+ fn mul(self, rhs: Conductance) -> Self::Output {
+ self.to_si_primitive() * rhs.to_si_primitive()
+ }
+} \ No newline at end of file
diff --git a/src/metric/dose_equivalent.rs b/src/metric/dose_equivalent.rs
new file mode 100644
index 0000000..408c7de
--- /dev/null
+++ b/src/metric/dose_equivalent.rs
@@ -0,0 +1,30 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+pub enum DoseEquivalent {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ Sievert(f64),
+ Gray(f64),
+}
+
+impl Unit<DoseEquivalent> for DoseEquivalent {
+ fn to_si_unit(&self) -> DoseEquivalent {
+ match self {
+ DoseEquivalent::Base(_, _, _) => self.clone(),
+ DoseEquivalent::Canonical(value) => DoseEquivalent::Base(value.clone(), |x| x, "Sv"),
+ DoseEquivalent::Sievert(value) => DoseEquivalent::Base(value.clone(), |x| x, "Sv"),
+ DoseEquivalent::Gray(value) => DoseEquivalent::Base(value.clone(), |x| x, "Gy"),
+ }
+ }
+}
+
+declare_unit_basics!(DoseEquivalent);
+
+pub type AbsorbedDose = DoseEquivalent; \ No newline at end of file
diff --git a/src/metric/electric_charge.rs b/src/metric/electric_charge.rs
new file mode 100644
index 0000000..9e6e970
--- /dev/null
+++ b/src/metric/electric_charge.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(ElectricCharge, Coulomb, "C"); \ No newline at end of file
diff --git a/src/metric/electric_current.rs b/src/metric/electric_current.rs
new file mode 100644
index 0000000..376e426
--- /dev/null
+++ b/src/metric/electric_current.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(ElectricCurrent, Ampere, "A"); \ No newline at end of file
diff --git a/src/metric/electric_potential.rs b/src/metric/electric_potential.rs
new file mode 100644
index 0000000..9fdbde8
--- /dev/null
+++ b/src/metric/electric_potential.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(ElectricPotential, Volt, "V"); \ No newline at end of file
diff --git a/src/metric/electric_resistance.rs b/src/metric/electric_resistance.rs
new file mode 100644
index 0000000..3d3d9f8
--- /dev/null
+++ b/src/metric/electric_resistance.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(ElectricResistance, Ohm, "Ω"); \ No newline at end of file
diff --git a/src/metric/energy.rs b/src/metric/energy.rs
new file mode 100644
index 0000000..5884a2f
--- /dev/null
+++ b/src/metric/energy.rs
@@ -0,0 +1,32 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+pub enum Energy {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ Joule(f64),
+ KiloJoule(f64),
+ Calorie(f64),
+ Kilocalorie(f64),
+}
+
+impl Unit<Energy> for Energy {
+ fn to_si_unit(&self) -> Energy {
+ match self {
+ Energy::Base(_, _, _) => self.clone(),
+ Energy::Canonical(value) => Energy::Base(value.clone(), |x| x, "J"),
+ Energy::Joule(value) => Energy::Base(value.clone(), |x| x, "J"),
+ Energy::KiloJoule(value) => Energy::Base(value * 1000.0, |x| x / 1000.0, "kJ"),
+ Energy::Calorie(value) => Energy::Base(value * 4.184, |x| x / 4.184, "cal"),
+ Energy::Kilocalorie(value) => Energy::Base(value * 4184.0, |x| x / 4184.0, "kcal"),
+ }
+ }
+}
+
+declare_unit_basics!(Energy); \ No newline at end of file
diff --git a/src/metric/force.rs b/src/metric/force.rs
new file mode 100644
index 0000000..5011ce6
--- /dev/null
+++ b/src/metric/force.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(Force, Newton, "N"); \ No newline at end of file
diff --git a/src/metric/frequency.rs b/src/metric/frequency.rs
new file mode 100644
index 0000000..c35f874
--- /dev/null
+++ b/src/metric/frequency.rs
@@ -0,0 +1,59 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+
+use crate::metric::time::Time;
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+pub enum Frequency {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ Hertz(f64),
+ Becquerel(f64),
+}
+
+impl Unit<Frequency> for Frequency {
+ fn to_si_unit(&self) -> Frequency {
+ match self {
+ Frequency::Base(_, _, _) => self.clone(),
+ Frequency::Canonical(value) => Frequency::Base(value.clone(), |x| x, "Hz"),
+ Frequency::Hertz(value) => Frequency::Base(value.clone(), |x| x, "Hz"),
+ Frequency::Becquerel(value) => Frequency::Base(value.clone(), |x| x, "Bq"),
+ }
+ }
+}
+
+declare_unit_basics!(Frequency);
+
+// 1/s = Hz
+impl Div<Time> for f64 {
+ type Output = Frequency;
+
+ fn div(self, rhs: Time) -> Self::Output {
+ Frequency::Canonical(self * rhs.to_si_primitive())
+ }
+}
+
+// Hz * s = 1
+impl Mul<Time> for Frequency {
+ type Output = f64;
+
+ fn mul(self, rhs: Time) -> Self::Output {
+ self.to_si_primitive() * rhs.to_si_primitive()
+ }
+}
+
+// s * Hz = 1
+impl Mul<Frequency> for Time {
+ type Output = f64;
+
+ fn mul(self, rhs: Frequency) -> Self::Output {
+ self.to_si_primitive() * rhs.to_si_primitive()
+ }
+}
+
+pub type Activity = Frequency; \ No newline at end of file
diff --git a/src/metric/illuminance.rs b/src/metric/illuminance.rs
new file mode 100644
index 0000000..a6010e0
--- /dev/null
+++ b/src/metric/illuminance.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(Illuminance, Lux, "lx"); \ No newline at end of file
diff --git a/src/metric/inductance.rs b/src/metric/inductance.rs
new file mode 100644
index 0000000..702e67a
--- /dev/null
+++ b/src/metric/inductance.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(Inductance, Henry, "H"); \ No newline at end of file
diff --git a/src/metric/length.rs b/src/metric/length.rs
new file mode 100644
index 0000000..a605ad2
--- /dev/null
+++ b/src/metric/length.rs
@@ -0,0 +1,44 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+pub enum Length {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ Meter(f64),
+ Metre(f64),
+ Centimeter(f64),
+ Centimetre(f64),
+ Kilometer(f64),
+ Kilometre(f64),
+ Inch(f64), // Zoll
+ Foot(f64), // Fuß
+ Yard(f64), // Schritt
+ Mile(f64), // Meile
+}
+
+impl Unit<Length> for Length {
+ fn to_si_unit(&self) -> Length {
+ match self {
+ Length::Base(_, _, _) => self.clone(),
+ Length::Canonical(value) => Length::Base(value.clone(), |x| x, "m"),
+ Length::Meter(value) => Length::Base(value.clone(), |x| x, "m"),
+ Length::Metre(value) => Length::Base(value.clone(), |x| x, "m"),
+ Length::Centimeter(value) => Length::Base(value / 100.0, |x| x * 100.0, "cm"),
+ Length::Centimetre(value) => Length::Base(value / 100.0, |x| x * 100.0, "cm"),
+ Length::Kilometer(value) => Length::Base(value * 1000.0, |x| x / 1000.0, "km"),
+ Length::Kilometre(value) => Length::Base(value * 1000.0, |x| x / 1000.0, "km"),
+ Length::Inch(value) => Length::Base(value * 0.0254, |x| x / 0.0254, "in"),
+ Length::Foot(value) => Length::Base(value * 0.3048, |x| x / 0.3048, "foot"),
+ Length::Yard(value) => Length::Base(value * 0.9144, |x| x / 0.9144, "yard"),
+ Length::Mile(value) => Length::Base(value * 1609.344, |x| x / 1609.344, "mile"),
+ }
+ }
+}
+
+declare_unit_basics!(Length); \ No newline at end of file
diff --git a/src/metric/luminous_flux.rs b/src/metric/luminous_flux.rs
new file mode 100644
index 0000000..ba3a296
--- /dev/null
+++ b/src/metric/luminous_flux.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(LuminousFlux, Lumen, "lm"); \ No newline at end of file
diff --git a/src/metric/luminous_intensity.rs b/src/metric/luminous_intensity.rs
new file mode 100644
index 0000000..d2bfe42
--- /dev/null
+++ b/src/metric/luminous_intensity.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(LuminousIntensity, Candela, "cd"); \ No newline at end of file
diff --git a/src/metric/magnetic_flux.rs b/src/metric/magnetic_flux.rs
new file mode 100644
index 0000000..8846a14
--- /dev/null
+++ b/src/metric/magnetic_flux.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(MagneticFlux, Weber, "Wb"); \ No newline at end of file
diff --git a/src/metric/magnetic_flux_density.rs b/src/metric/magnetic_flux_density.rs
new file mode 100644
index 0000000..1d6a58c
--- /dev/null
+++ b/src/metric/magnetic_flux_density.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(MagneticFluxDensity, Tesla, "T"); \ No newline at end of file
diff --git a/src/metric/mass.rs b/src/metric/mass.rs
new file mode 100644
index 0000000..462d840
--- /dev/null
+++ b/src/metric/mass.rs
@@ -0,0 +1,36 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+pub enum Mass {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ Kilogram(f64),
+ Milligram(f64),
+ Gram(f64),
+ Tonne(f64),
+ Ounce(f64), // international avoirdupois ounce
+ Pound(f64), // International avoirdupois pound
+}
+
+impl Unit<Mass> for Mass {
+ fn to_si_unit(&self) -> Mass {
+ match self {
+ Mass::Base(_, _, _) => self.clone(),
+ Mass::Canonical(value) => Mass::Base(value.clone(), |x| x, "kg"),
+ Mass::Kilogram(value) => Mass::Base(value.clone(), |x| x, "kg"),
+ Mass::Gram(value) => Mass::Base(value / 1000.0, |x| x * 1000.0, "g"),
+ Mass::Milligram(value) => Mass::Base(value / 1_000_000.0, |x| x * 1_000_000.0, "mg"),
+ Mass::Tonne(value) => Mass::Base(value * 1000.0, |x| x / 1000.0, "t"),
+ Mass::Ounce(value) => Mass::Base(value * 28.349523125 / 1000.0, |x| x / 28.349523125 * 1000.0, "℥"),
+ Mass::Pound(value) => Mass::Base(value * 0.45359237, |x| x / 0.45359237, "lb"),
+ }
+ }
+}
+
+declare_unit_basics!(Mass); \ No newline at end of file
diff --git a/src/metric/plane_angle.rs b/src/metric/plane_angle.rs
new file mode 100644
index 0000000..86bc17c
--- /dev/null
+++ b/src/metric/plane_angle.rs
@@ -0,0 +1,28 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+pub enum PlaneAngle {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ Radian(f64),
+ Degree(f64),
+}
+
+impl Unit<PlaneAngle> for PlaneAngle {
+ fn to_si_unit(&self) -> PlaneAngle {
+ match self {
+ PlaneAngle::Base(_, _, _) => self.clone(),
+ PlaneAngle::Canonical(value) => PlaneAngle::Base(value.clone(), |x| x, "m²"),
+ PlaneAngle::Radian(value) => PlaneAngle::Base(value.clone(), |x| x, "rad"),
+ PlaneAngle::Degree(value) => PlaneAngle::Base(value * std::f64::consts::PI / 180.0, |x| x / std::f64::consts::PI * 180.0, "°"),
+ }
+ }
+}
+
+declare_unit_basics!(PlaneAngle); \ No newline at end of file
diff --git a/src/metric/power.rs b/src/metric/power.rs
new file mode 100644
index 0000000..51d6cf0
--- /dev/null
+++ b/src/metric/power.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(Power, Watt, "W"); \ No newline at end of file
diff --git a/src/metric/pressure.rs b/src/metric/pressure.rs
new file mode 100644
index 0000000..b28c87c
--- /dev/null
+++ b/src/metric/pressure.rs
@@ -0,0 +1,28 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+pub enum Pressure {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ Pascal(f64),
+ Bar(f64),
+}
+
+impl Unit<Pressure> for Pressure {
+ fn to_si_unit(&self) -> Pressure {
+ match self {
+ Pressure::Base(_, _, _) => self.clone(),
+ Pressure::Canonical(value) => Pressure::Base(value.clone(), |x| x, "Pa"),
+ Pressure::Pascal(value) => Pressure::Base(value.clone(), |x| x, "Pa"),
+ Pressure::Bar(value) => Pressure::Base(value * 100_000.0, |x| x / 100_000.0, "bar"),
+ }
+ }
+}
+
+declare_unit_basics!(Pressure); \ No newline at end of file
diff --git a/src/metric/solid_angle.rs b/src/metric/solid_angle.rs
new file mode 100644
index 0000000..9db73ef
--- /dev/null
+++ b/src/metric/solid_angle.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(SolidAngle, Sterdian, "sr"); \ No newline at end of file
diff --git a/src/metric/temperature.rs b/src/metric/temperature.rs
new file mode 100644
index 0000000..06c1489
--- /dev/null
+++ b/src/metric/temperature.rs
@@ -0,0 +1,89 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+pub enum ThermodynamicTemperature {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ Kelvin(f64),
+}
+
+impl Unit<ThermodynamicTemperature> for ThermodynamicTemperature {
+ fn to_si_unit(&self) -> ThermodynamicTemperature {
+ match self {
+ ThermodynamicTemperature::Base(_, _, _) => self.clone(),
+ ThermodynamicTemperature::Canonical(value) => ThermodynamicTemperature::Base(value.clone(), |x| x, "K"),
+ ThermodynamicTemperature::Kelvin(value) => ThermodynamicTemperature::Base(value.clone(), |x| x, "K"),
+ }
+ }
+}
+
+declare_unit_basics!(ThermodynamicTemperature);
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+pub enum CelsiusTemperature {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ Celsius(f64),
+ Fahrenheit(f64),
+}
+
+impl Unit<CelsiusTemperature> for CelsiusTemperature {
+ fn to_si_unit(&self) -> CelsiusTemperature {
+ match self {
+ CelsiusTemperature::Base(_, _, _) => self.clone(),
+ CelsiusTemperature::Canonical(value) => CelsiusTemperature::Base(value.clone(), |x| x, "K"),
+ CelsiusTemperature::Celsius(value) => CelsiusTemperature::Base(value.clone(), |x| x, "°C"),
+ CelsiusTemperature::Fahrenheit(value) => CelsiusTemperature::Base((value - 32.0) / 1.8 , |x| x * 1.8 + 32.0, "°F"),
+ }
+ }
+}
+
+declare_unit_basics!(CelsiusTemperature);
+
+/* --- temperature interoperability: C +/- K --- */
+
+impl Add<ThermodynamicTemperature> for CelsiusTemperature {
+ type Output = CelsiusTemperature;
+
+ fn add(self, rhs: ThermodynamicTemperature) -> Self::Output {
+ match self.to_si_unit() {
+ CelsiusTemperature::Base(value, from_si, symbol) => CelsiusTemperature::Base(value + rhs.to_si_primitive(), from_si, symbol),
+ _ => panic!("non si unit post to_si_unit() call")
+ }
+ }
+}
+
+impl AddAssign<ThermodynamicTemperature> for CelsiusTemperature {
+ fn add_assign(&mut self, rhs: ThermodynamicTemperature) {
+ match self.to_si_unit() {
+ CelsiusTemperature::Base(value, from_si, symbol) => *self = CelsiusTemperature::Base(value + rhs.to_si_primitive(), from_si, symbol),
+ _ => panic!("non si unit post to_si_unit() call")
+ }
+ }
+}
+
+impl Sub<ThermodynamicTemperature> for CelsiusTemperature {
+ type Output = CelsiusTemperature;
+
+ fn sub(self, rhs: ThermodynamicTemperature) -> Self::Output {
+ match self.to_si_unit() {
+ CelsiusTemperature::Base(value, from_si, symbol) => CelsiusTemperature::Base(value + rhs.to_si_primitive(), from_si, symbol),
+ _ => panic!("non si unit post to_si_unit() call")
+ }
+ }
+}
+
+impl SubAssign<ThermodynamicTemperature> for CelsiusTemperature {
+ fn sub_assign(&mut self, rhs: ThermodynamicTemperature) {
+ match self.to_si_unit() {
+ CelsiusTemperature::Base(value, from_si, symbol) => *self = CelsiusTemperature::Base(value - rhs.to_si_primitive(), from_si, symbol),
+ _ => panic!("non si unit post to_si_unit() call")
+ }
+ }
+} \ No newline at end of file
diff --git a/src/metric/time.rs b/src/metric/time.rs
new file mode 100644
index 0000000..f4ff4b8
--- /dev/null
+++ b/src/metric/time.rs
@@ -0,0 +1,36 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+pub enum Time {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ Second(f64),
+ Millisecond(f64),
+ Minute(f64),
+ Hour(f64),
+ Day(f64),
+ Year(f64),
+}
+
+impl Unit<Time> for Time {
+ fn to_si_unit(&self) -> Time {
+ match self {
+ Time::Base(_, _, _) => self.clone(),
+ Time::Canonical(value) => Time::Base(value.clone(), |x| x, "s"),
+ Time::Second(value) => Time::Base(value.clone(), |x| x, "s"),
+ Time::Millisecond(value) => Time::Base(value / 1000.0, |x| x * 1000.0, "ms"),
+ Time::Minute(value) => Time::Base(value * 60.0, |x| x / 60.0, "min"),
+ Time::Hour(value) => Time::Base(value * 3600.0, |x| x / 3600.0, "h"),
+ Time::Day(value) => Time::Base(value * 86400.0, |x| x / 86400.0, "d"),
+ Time::Year(value) => Time::Base(value * 31536000.0, |x| x / 31536000.0, "a")
+ }
+ }
+}
+
+declare_unit_basics!(Time); \ No newline at end of file
diff --git a/src/metric/velocity.rs b/src/metric/velocity.rs
new file mode 100644
index 0000000..3aa65d0
--- /dev/null
+++ b/src/metric/velocity.rs
@@ -0,0 +1,10 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+use crate::declare_simple_unit;
+
+declare_simple_unit!(Velocity, Speed, "m/s"); \ No newline at end of file
diff --git a/src/metric/volume.rs b/src/metric/volume.rs
new file mode 100644
index 0000000..064912d
--- /dev/null
+++ b/src/metric/volume.rs
@@ -0,0 +1,32 @@
+use std::fmt::{Display, Formatter, Result};
+use std::ops::{Add, Sub, AddAssign, SubAssign, Div, Mul, DivAssign, MulAssign};
+
+use crate::metric::Unit;
+use crate::metric::Primitive;
+
+use crate::declare_unit_basics;
+
+#[derive(Copy, Clone, PartialOrd, PartialEq)]
+pub enum Volume {
+ Base(f64, fn(f64) -> f64, &'static str),
+ Canonical(f64),
+ CubicMeter(f64),
+ CubicMetre(f64),
+ Litre(f64),
+ Liter(f64)
+}
+
+impl Unit<Volume> for Volume {
+ fn to_si_unit(&self) -> Volume {
+ match self {
+ Volume::Base(_, _, _) => self.clone(),
+ Volume::Canonical(value) => Volume::Base(value.clone(), |x| x, "m³"),
+ Volume::CubicMeter(value) => Volume::Base(value.clone(), |x| x, "m³"),
+ Volume::CubicMetre(value) => Volume::Base(value.clone(), |x| x, "m³"),
+ Volume::Litre(value) => Volume::Base(value / 1000.0, |x| x * 1000.0, "l"),
+ Volume::Liter(value) => Volume::Base(value / 1000.0, |x| x * 1000.0, "l"),
+ }
+ }
+}
+
+declare_unit_basics!(Volume); \ No newline at end of file